[automerger skipped] getCallingSid: get calling security context am: 683b6d043d am: d7acd8a870 -s ours
am: 7e6b6dfb36 -s ours
am skip reason: change_id Ia8a4c0cb4a9c86dcc0d3b7583014237f879a3074 with SHA1 f0a7d7899e is in history

Change-Id: I310b74e061f79339b08dbfb246daa08208b49706
diff --git a/Android.bp b/Android.bp
index b62d197..4214d85 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,8 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_library_shared {
-    name: "libhwbinder",
+subdirs = [
+    "vts/performance",
+]
+
+cc_defaults {
+    name: "libhwbinder_defaults",
     shared_libs: [
         "libbase",
         "liblog",
@@ -55,5 +59,49 @@
         },
     },
 
-    cflags: ["-Werror"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
+
+cc_library {
+    name: "libhwbinder",
+    defaults: [
+        "libhwbinder_defaults",
+        "hwbinder_pgo",
+        "hwbinder_lto"
+    ],
+}
+
+// Explicitly provide a no lto, no PGO variant, to workaround the issue that we
+// can't detect non-lto users of the module in Android.mk.
+// http://b/77320844
+cc_library {
+    name: "libhwbinder_noltopgo",
+    defaults: [
+        "libhwbinder_defaults",
+    ],
+}
+
+// Provide pgo property to build hwbinder with PGO
+cc_defaults {
+    name: "hwbinder_pgo",
+    pgo: {
+        instrumentation: true,
+        profile_file: "hwbinder/hwbinder.profdata",
+        benchmarks: ["hwbinder"],
+        enable_profile_use: true,
+    },
+}
+// Provide lto property to build hwbinder with LTO
+cc_defaults {
+    name: "hwbinder_lto",
+    target: {
+        android: {
+            lto: {
+                thin: true,
+            },
+        },
+    },
 }
diff --git a/Binder.cpp b/Binder.cpp
index b6a58ff..147c7ca 100644
--- a/Binder.cpp
+++ b/Binder.cpp
@@ -219,11 +219,8 @@
 BpHwRefBase::BpHwRefBase(const sp<IBinder>& o)
     : mRemote(o.get()), mRefs(NULL), mState(0)
 {
-    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
-
     if (mRemote) {
         mRemote->incStrong(this);           // Removed on first IncStrong().
-        mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.
     }
 }
 
@@ -233,7 +230,6 @@
         if (!(mState.load(std::memory_order_relaxed)&kRemoteAcquired)) {
             mRemote->decStrong(this);
         }
-        mRefs->decWeak(this);
     }
 }
 
@@ -251,7 +247,7 @@
 
 bool BpHwRefBase::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
 {
-    return mRemote ? mRefs->attemptIncStrong(this) : false;
+    return false;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/BpHwBinder.cpp b/BpHwBinder.cpp
index ed7ed2a..90b3c6f 100644
--- a/BpHwBinder.cpp
+++ b/BpHwBinder.cpp
@@ -96,7 +96,7 @@
     ALOGV("Creating BpHwBinder %p handle %d\n", this, mHandle);
 
     extendObjectLifetime(OBJECT_LIFETIME_WEAK);
-    IPCThreadState::self()->incWeakHandle(handle);
+    IPCThreadState::self()->incWeakHandle(handle, this);
 }
 
 status_t BpHwBinder::transact(
@@ -282,7 +282,7 @@
 {
     ALOGV("onFirstRef BpHwBinder %p handle %d\n", this, mHandle);
     IPCThreadState* ipc = IPCThreadState::self();
-    if (ipc) ipc->incStrongHandle(mHandle);
+    if (ipc) ipc->incStrongHandle(mHandle, this);
 }
 
 void BpHwBinder::onLastStrongRef(const void* /*id*/)
diff --git a/BufferedTextOutput.cpp b/BufferedTextOutput.cpp
index 8ef48e1..9bddde5 100644
--- a/BufferedTextOutput.cpp
+++ b/BufferedTextOutput.cpp
@@ -19,11 +19,11 @@
 #include <hwbinder/BufferedTextOutput.h>
 #include <hwbinder/Debug.h>
 
-#include <utils/Atomic.h>
+#include <cutils/atomic.h>
+#include <cutils/threads.h>
 #include <utils/Log.h>
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
-#include <cutils/threads.h>
 
 #include <hwbinder/Static.h>
 
diff --git a/Debug.cpp b/Debug.cpp
index fb97069..d304d21 100644
--- a/Debug.cpp
+++ b/Debug.cpp
@@ -222,7 +222,11 @@
 
         for (word = 0; word < bytesPerLine; ) {
 
-            const size_t startIndex = word+(alignment-(alignment?1:0));
+            size_t align_offset = alignment-(alignment?1:0);
+            if (remain > 0 && (size_t)remain <= align_offset) {
+                align_offset = remain - 1;
+            }
+            const size_t startIndex = word+align_offset;
 
             for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
 
diff --git a/IPCThreadState.cpp b/IPCThreadState.cpp
index b9ca20a..b36838e 100644
--- a/IPCThreadState.cpp
+++ b/IPCThreadState.cpp
@@ -412,6 +412,15 @@
     if (mProcess->mDriverFD <= 0)
         return;
     talkWithDriver(false);
+    // The flush could have caused post-write refcount decrements to have
+    // been executed, which in turn could result in BC_RELEASE/BC_DECREFS
+    // being queued in mOut. So flush again, if we need to.
+    if (mOut.dataSize() > 0) {
+        talkWithDriver(false);
+    }
+    if (mOut.dataSize() > 0) {
+        ALOGW("mOut.dataSize() > 0 after flushCommands()");
+    }
 }
 
 void IPCThreadState::blockUntilThreadAvailable()
@@ -453,12 +462,15 @@
 
         pthread_mutex_lock(&mProcess->mThreadCountLock);
         mProcess->mExecutingThreadsCount--;
-        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads && mProcess->mMaxThreads > 1 &&
+        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
             mProcess->mStarvationStartTimeMs != 0) {
             int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;
             if (starvationTimeMs > 100) {
-                ALOGW("All binder threads in pool (%zu threads) busy for %" PRId64 " ms",
-                      mProcess->mMaxThreads, starvationTimeMs);
+                // If there is only a single-threaded client, nobody would be blocked
+                // on this, and it's not really starvation. (see b/37647467)
+                ALOGW("All binder threads in pool (%zu threads) busy for %" PRId64 " ms%s",
+                      mProcess->mMaxThreads, starvationTimeMs,
+                      mProcess->mMaxThreads > 1 ? "" : " (may be a false alarm)");
             }
             mProcess->mStarvationStartTimeMs = 0;
         }
@@ -473,26 +485,58 @@
 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++) {
-                BHwBinder* 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.
+                BHwBinder* obj = mPendingStrongDerefs[0];
+                mPendingStrongDerefs.removeAt(0);
                 obj->decStrong(mProcess.get());
             }
-            mPendingStrongDerefs.clear();
         }
     }
 }
 
+void IPCThreadState::processPostWriteDerefs()
+{
+    /*
+     * libhwbinder has a flushCommands() in the BpHwBinder destructor,
+     * which makes this function (potentially) reentrant.
+     * New entries shouldn't be added though, so just iterating until empty
+     * should be safe.
+     */
+    while (mPostWriteWeakDerefs.size() > 0) {
+        RefBase::weakref_type* refs = mPostWriteWeakDerefs[0];
+        mPostWriteWeakDerefs.removeAt(0);
+        refs->decWeak(mProcess.get());
+    }
+
+    while (mPostWriteStrongDerefs.size() > 0) {
+        RefBase* obj = mPostWriteStrongDerefs[0];
+        mPostWriteStrongDerefs.removeAt(0);
+        obj->decStrong(mProcess.get());
+    }
+}
+
 void IPCThreadState::joinThreadPool(bool isMain)
 {
     LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
@@ -500,6 +544,7 @@
     mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
 
     status_t result;
+    mIsLooper = true;
     do {
         processPendingDerefs();
         // now get the next command to be processed, waiting if necessary
@@ -522,6 +567,7 @@
         (void*)pthread_self(), getpid(), result);
 
     mOut.writeInt32(BC_EXIT_LOOPER);
+    mIsLooper = false;
     talkWithDriver(false);
 }
 
@@ -531,6 +577,12 @@
         return -EBADF;
     }
 
+    // Tells the kernel to not spawn any additional binder threads,
+    // as that won't work with polling. Also, the caller is responsible
+    // for subsequently calling handlePolledCommands()
+    mProcess->setThreadPoolConfiguration(1, true /* callerWillJoin */);
+    mIsPollingThread = true;
+
     mOut.writeInt32(BC_ENTER_LOOPER);
     *fd = mProcess->mDriverFD;
     return 0;
@@ -563,7 +615,7 @@
                                   uint32_t code, const Parcel& data,
                                   Parcel* reply, uint32_t flags)
 {
-    status_t err = data.errorCheck();
+    status_t err;
 
     flags |= TF_ACCEPT_FDS;
 
@@ -573,11 +625,9 @@
             << indent << data << dedent << endl;
     }
 
-    if (err == NO_ERROR) {
-        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
-            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
-        err = writeTransactionData(BC_TRANSACTION_SG, flags, handle, code, data, NULL);
-    }
+    LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
+        (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
+    err = writeTransactionData(BC_TRANSACTION_SG, flags, handle, code, data, NULL);
 
     if (err != NO_ERROR) {
         if (reply) reply->setError(err);
@@ -619,11 +669,14 @@
     return err;
 }
 
-void IPCThreadState::incStrongHandle(int32_t handle)
+void IPCThreadState::incStrongHandle(int32_t handle, BpHwBinder *proxy)
 {
     LOG_REMOTEREFS("IPCThreadState::incStrongHandle(%d)\n", handle);
     mOut.writeInt32(BC_ACQUIRE);
     mOut.writeInt32(handle);
+    // Create a temp reference until the driver has handled this command.
+    proxy->incStrong(mProcess.get());
+    mPostWriteStrongDerefs.push(proxy);
 }
 
 void IPCThreadState::decStrongHandle(int32_t handle)
@@ -633,11 +686,14 @@
     mOut.writeInt32(handle);
 }
 
-void IPCThreadState::incWeakHandle(int32_t handle)
+void IPCThreadState::incWeakHandle(int32_t handle, BpHwBinder *proxy)
 {
     LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle);
     mOut.writeInt32(BC_INCREFS);
     mOut.writeInt32(handle);
+    // Create a temp reference until the driver has handled this command.
+    proxy->getWeakRefs()->incWeak(mProcess.get());
+    mPostWriteWeakDerefs.push(proxy->getWeakRefs());
 }
 
 void IPCThreadState::decWeakHandle(int32_t handle)
@@ -676,7 +732,7 @@
 #if LOG_REFCOUNTS
     printf("IPCThreadState::expungeHandle(%ld)\n", handle);
 #endif
-    self()->mProcess->expungeHandle(handle, binder);
+    self()->mProcess->expungeHandle(handle, binder);  // NOLINT
 }
 
 status_t IPCThreadState::requestDeathNotification(int32_t handle, BpHwBinder* proxy)
@@ -699,12 +755,16 @@
     : mProcess(ProcessState::self()),
       mMyThreadId(gettid()),
       mStrictModePolicy(0),
-      mLastTransactionBinderFlags(0)
-{
+      mLastTransactionBinderFlags(0),
+      mIsLooper(false),
+      mIsPollingThread(false) {
     pthread_setspecific(gTLS, this);
     clearCaller();
     mIn.setDataCapacity(256);
     mOut.setDataCapacity(256);
+
+    // TODO(b/67742352): remove this variable from the class
+    (void)mMyThreadId;
 }
 
 IPCThreadState::~IPCThreadState()
@@ -889,8 +949,10 @@
         if (bwr.write_consumed > 0) {
             if (bwr.write_consumed < mOut.dataSize())
                 mOut.remove(0, bwr.write_consumed);
-            else
+            else {
                 mOut.setDataSize(0);
+                processPostWriteDerefs();
+            }
         }
         if (bwr.read_consumed > 0) {
             mIn.setDataSize(bwr.read_consumed);
@@ -915,28 +977,29 @@
     int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
 {
     binder_transaction_data_sg tr_sg;
-    tr_sg.tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
-    tr_sg.tr.target.handle = handle;
-    tr_sg.tr.code = code;
-    tr_sg.tr.flags = binderFlags;
-    tr_sg.tr.cookie = 0;
-    tr_sg.tr.sender_pid = 0;
-    tr_sg.tr.sender_euid = 0;
+    /* Don't pass uninitialized stack data to a remote process */
+    tr_sg.transaction_data.target.ptr = 0;
+    tr_sg.transaction_data.target.handle = handle;
+    tr_sg.transaction_data.code = code;
+    tr_sg.transaction_data.flags = binderFlags;
+    tr_sg.transaction_data.cookie = 0;
+    tr_sg.transaction_data.sender_pid = 0;
+    tr_sg.transaction_data.sender_euid = 0;
 
     const status_t err = data.errorCheck();
     if (err == NO_ERROR) {
-        tr_sg.tr.data_size = data.ipcDataSize();
-        tr_sg.tr.data.ptr.buffer = data.ipcData();
-        tr_sg.tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
-        tr_sg.tr.data.ptr.offsets = data.ipcObjects();
+        tr_sg.transaction_data.data_size = data.ipcDataSize();
+        tr_sg.transaction_data.data.ptr.buffer = data.ipcData();
+        tr_sg.transaction_data.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
+        tr_sg.transaction_data.data.ptr.offsets = data.ipcObjects();
         tr_sg.buffers_size = data.ipcBufferSize();
     } else if (statusBuffer) {
-        tr_sg.tr.flags |= TF_STATUS_CODE;
+        tr_sg.transaction_data.flags |= TF_STATUS_CODE;
         *statusBuffer = err;
-        tr_sg.tr.data_size = sizeof(status_t);
-        tr_sg.tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
-        tr_sg.tr.offsets_size = 0;
-        tr_sg.tr.data.ptr.offsets = 0;
+        tr_sg.transaction_data.data_size = sizeof(status_t);
+        tr_sg.transaction_data.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
+        tr_sg.transaction_data.offsets_size = 0;
+        tr_sg.transaction_data.data.ptr.offsets = 0;
         tr_sg.buffers_size = 0;
     } else {
         return (mLastError = err);
@@ -953,6 +1016,15 @@
     mContextObject = obj;
 }
 
+bool IPCThreadState::isLooperThread()
+{
+    return mIsLooper;
+}
+
+bool IPCThreadState::isOnlyBinderThread() {
+    return (mIsLooper && mProcess->mMaxThreads <= 1) || mIsPollingThread;
+}
+
 status_t IPCThreadState::executeCommand(int32_t cmd)
 {
     BHwBinder* obj;
diff --git a/Parcel.cpp b/Parcel.cpp
index 7f80c01..2b1bb90 100644
--- a/Parcel.cpp
+++ b/Parcel.cpp
@@ -98,7 +98,7 @@
 void acquire_binder_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who)
 {
-    switch (obj.type) {
+    switch (obj.hdr.type) {
         case BINDER_TYPE_BINDER:
             if (obj.binder) {
                 LOG_REFS("Parcel %p acquiring reference on local %p", who, obj.cookie);
@@ -124,7 +124,7 @@
         }
     }
 
-    ALOGD("Invalid object type 0x%08x", obj.type);
+    ALOGD("Invalid object type 0x%08x", obj.hdr.type);
 }
 
 void acquire_object(const sp<ProcessState>& proc, const binder_object_header& obj,
@@ -144,7 +144,7 @@
 void release_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who)
 {
-    switch (obj.type) {
+    switch (obj.hdr.type) {
         case BINDER_TYPE_BINDER:
             if (obj.binder) {
                 LOG_REFS("Parcel %p releasing reference on local %p", who, obj.cookie);
@@ -184,7 +184,7 @@
         }
     }
 
-    ALOGE("Invalid object type 0x%08x", obj.type);
+    ALOGE("Invalid object type 0x%08x", obj.hdr.type);
 }
 
 inline static status_t finish_flatten_binder(
@@ -206,7 +206,7 @@
                 ALOGE("null proxy");
             }
             const int32_t handle = proxy ? proxy->handle() : 0;
-            obj.type = BINDER_TYPE_HANDLE;
+            obj.hdr.type = BINDER_TYPE_HANDLE;
             obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
             obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
             obj.handle = handle;
@@ -222,12 +222,12 @@
             if (local->isRequestingSid()) {
                 obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
             }
-            obj.type = BINDER_TYPE_BINDER;
+            obj.hdr.type = BINDER_TYPE_BINDER;
             obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
             obj.cookie = reinterpret_cast<uintptr_t>(local);
         }
     } else {
-        obj.type = BINDER_TYPE_BINDER;
+        obj.hdr.type = BINDER_TYPE_BINDER;
         obj.binder = 0;
         obj.cookie = 0;
     }
@@ -251,12 +251,12 @@
                     ALOGE("null proxy");
                 }
                 const int32_t handle = proxy ? proxy->handle() : 0;
-                obj.type = BINDER_TYPE_WEAK_HANDLE;
+                obj.hdr.type = BINDER_TYPE_WEAK_HANDLE;
                 obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
                 obj.handle = handle;
                 obj.cookie = 0;
             } else {
-                obj.type = BINDER_TYPE_WEAK_BINDER;
+                obj.hdr.type = BINDER_TYPE_WEAK_BINDER;
                 obj.binder = reinterpret_cast<uintptr_t>(binder.get_refs());
                 obj.cookie = reinterpret_cast<uintptr_t>(binder.unsafe_get());
             }
@@ -271,13 +271,13 @@
         // but we can't do that with the different reference counting
         // implementation we are using.
         ALOGE("Unable to unflatten Binder weak reference!");
-        obj.type = BINDER_TYPE_BINDER;
+        obj.hdr.type = BINDER_TYPE_BINDER;
         obj.binder = 0;
         obj.cookie = 0;
         return finish_flatten_binder(NULL, obj, out);
 
     } else {
-        obj.type = BINDER_TYPE_BINDER;
+        obj.hdr.type = BINDER_TYPE_BINDER;
         obj.binder = 0;
         obj.cookie = 0;
         return finish_flatten_binder(NULL, obj, out);
@@ -297,7 +297,7 @@
     const flat_binder_object* flat = in.readObject<flat_binder_object>();
 
     if (flat) {
-        switch (flat->type) {
+        switch (flat->hdr.type) {
             case BINDER_TYPE_BINDER:
                 *out = reinterpret_cast<IBinder*>(flat->cookie);
                 return finish_unflatten_binder(NULL, *flat, in);
@@ -316,7 +316,7 @@
     const flat_binder_object* flat = in.readObject<flat_binder_object>();
 
     if (flat) {
-        switch (flat->type) {
+        switch (flat->hdr.type) {
             case BINDER_TYPE_BINDER:
                 *out = reinterpret_cast<IBinder*>(flat->cookie);
                 return finish_unflatten_binder(NULL, *flat, in);
@@ -342,12 +342,12 @@
 /*
  * Return true iff:
  * 1. obj is indeed a binder_buffer_object (type is BINDER_TYPE_PTR), and
- * 2. obj does NOT have the flag BINDER_BUFFER_REF (it is not a reference, but
+ * 2. obj does NOT have the flag BINDER_BUFFER_FLAG_REF (it is not a reference, but
  *    an actual buffer.)
  */
 static inline bool isBuffer(const binder_buffer_object& obj) {
     return obj.hdr.type == BINDER_TYPE_PTR
-        && (obj.flags & BINDER_BUFFER_REF) == 0;
+        && (obj.flags & BINDER_BUFFER_FLAG_REF) == 0;
 }
 
 // ---------------------------------------------------------------------------
@@ -753,7 +753,6 @@
                 break;
             }
             case BINDER_TYPE_FD: {
-                const binder_fd_object *fd_obj = reinterpret_cast<const binder_fd_object*>(hdr);
                 // remember if it's a file descriptor
                 if (!mAllowFds) {
                     // fail before modifying our object index
@@ -847,7 +846,7 @@
     obj.hdr.type = BINDER_TYPE_PTR;
     obj.buffer = reinterpret_cast<binder_uintptr_t>(buffer);
     obj.length = length;
-    obj.flags = BINDER_BUFFER_HAS_PARENT;
+    obj.flags = BINDER_BUFFER_FLAG_HAS_PARENT;
     if(!validateBufferParent(parent_buffer_handle, parent_offset))
         return BAD_VALUE;
     obj.parent = parent_buffer_handle;
@@ -891,11 +890,13 @@
         return status;
     binder_buffer_object obj;
     obj.hdr.type = BINDER_TYPE_PTR;
-    obj.flags = BINDER_BUFFER_REF;
+    obj.flags = BINDER_BUFFER_FLAG_REF;
     if (!validateBufferChild(child_buffer_handle, child_offset))
         return BAD_VALUE;
-    obj.child = child_buffer_handle;
-    obj.child_offset = child_offset;
+    // The current binder.h does not have child and child_offset names yet.
+    // Use the buffer and length parameters.
+    obj.buffer = child_buffer_handle;
+    obj.length = child_offset;
     if (handle != nullptr)
         // We use an index into mObjects as a handle
         *handle = mObjectsSize;
@@ -916,11 +917,13 @@
         return status;
     binder_buffer_object obj;
     obj.hdr.type = BINDER_TYPE_PTR;
-    obj.flags = BINDER_BUFFER_REF | BINDER_BUFFER_HAS_PARENT;
+    obj.flags = BINDER_BUFFER_FLAG_REF | BINDER_BUFFER_FLAG_HAS_PARENT;
     if (!validateBufferChild(child_buffer_handle, child_offset))
         return BAD_VALUE;
-    obj.child = child_buffer_handle;
-    obj.child_offset = child_offset;
+    // The current binder.h does not have child and child_offset names yet.
+    // Use the buffer and length parameters.
+    obj.buffer = child_buffer_handle;
+    obj.length = child_offset;
     if(!validateBufferParent(parent_buffer_handle, parent_offset))
         return BAD_VALUE;
     obj.parent = parent_buffer_handle;
@@ -939,7 +942,7 @@
         return status;
     binder_buffer_object obj;
     obj.hdr.type = BINDER_TYPE_PTR;
-    obj.flags = BINDER_BUFFER_REF;
+    obj.flags = BINDER_BUFFER_FLAG_REF;
     if (handle != nullptr)
         // We use an index into mObjects as a handle
         *handle = mObjectsSize;
@@ -957,7 +960,7 @@
         return status;
     binder_buffer_object obj;
     obj.hdr.type = BINDER_TYPE_PTR;
-    obj.flags = BINDER_BUFFER_REF | BINDER_BUFFER_HAS_PARENT;
+    obj.flags = BINDER_BUFFER_FLAG_REF | BINDER_BUFFER_FLAG_HAS_PARENT;
     // parent_buffer_handle and parent_offset needs to be checked.
     if(!validateBufferParent(parent_buffer_handle, parent_offset))
         return BAD_VALUE;
@@ -1050,7 +1053,6 @@
     struct binder_fd_array_object fd_array;
     size_t buffer_handle;
     status_t status = OK;
-    uint32_t flags = 0;
 
     if (handle == nullptr) {
         status = writeUint64(0);
@@ -1543,7 +1545,7 @@
         return false;
     }
 
-    if (flags & BINDER_BUFFER_HAS_PARENT) {
+    if (flags & BINDER_BUFFER_FLAG_HAS_PARENT) {
         if (buffer_obj->parent != parent) {
             ALOGE("Buffer parent %" PRIu64 " does not match expected parent %zu.",
                   static_cast<uint64_t>(buffer_obj->parent), parent);
@@ -1563,8 +1565,6 @@
                             uint32_t flags, size_t parent, size_t parentOffset,
                             const void **buffer_out) const {
 
-    status_t status = OK;
-
     const binder_buffer_object* buffer_obj = readObject<binder_buffer_object>(buffer_handle);
 
     if (buffer_obj == nullptr || !isBuffer(*buffer_obj)) {
@@ -1621,7 +1621,7 @@
                                             size_t parent_offset,
                                             const void **buffer_out) const
 {
-    return readBuffer(buffer_size, buffer_handle, BINDER_BUFFER_HAS_PARENT,
+    return readBuffer(buffer_size, buffer_handle, BINDER_BUFFER_FLAG_HAS_PARENT,
                       parent_buffer_handle, parent_offset, buffer_out);
 }
 
@@ -1641,7 +1641,7 @@
             *buffer_handle = 0; // TODO fix this, as readBuffer would do
         }
         if(isRef != nullptr) {
-            *isRef = (buffer_obj->flags & BINDER_BUFFER_REF) != 0;
+            *isRef = (buffer_obj->flags & BINDER_BUFFER_FLAG_REF) != 0;
             LOG_BUFFER("    readReference: isRef = %d", *isRef);
         }
         // in read side, always use .buffer and .length.
@@ -1786,7 +1786,7 @@
         i--;
         const flat_binder_object* flat
             = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]);
-        if (flat->type == BINDER_TYPE_FD) {
+        if (flat->hdr.type == BINDER_TYPE_FD) {
             //ALOGI("Closing fd: %ld", flat->handle);
             close(flat->handle);
         }
@@ -1884,7 +1884,7 @@
         for (size_t i=0; i<N; i++) {
             const flat_binder_object* flat
                 = reinterpret_cast<const flat_binder_object*>(DATA+OBJS[i]);
-            if (flat->type == BINDER_TYPE_PTR) {
+            if (flat->hdr.type == BINDER_TYPE_PTR) {
                 const binder_buffer_object* buffer
                     = reinterpret_cast<const binder_buffer_object*>(DATA+OBJS[i]);
                 if(isBuffer(*buffer)) {
@@ -1897,7 +1897,7 @@
                 }
             } else {
                 to << endl << "Object #" << i << " @ " << (void*)OBJS[i] << ": "
-                    << TypeCode(flat->type & 0x7f7f7f00)
+                    << TypeCode(flat->hdr.type & 0x7f7f7f00)
                     << " = " << flat->binder;
             }
         }
@@ -2122,7 +2122,7 @@
             for (size_t i=objectsSize; i<mObjectsSize; i++) {
                 const flat_binder_object* flat
                     = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]);
-                if (flat->type == BINDER_TYPE_FD) {
+                if (flat->hdr.type == BINDER_TYPE_FD) {
                     // will need to rescan because we may have lopped off the only FDs
                     mFdsKnown = false;
                 }
@@ -2151,7 +2151,7 @@
                 pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
                 mData = data;
                 mDataCapacity = desired;
-            } else if (desired > mDataCapacity) {
+            } else {
                 mError = NO_MEMORY;
                 return NO_MEMORY;
             }
@@ -2235,7 +2235,7 @@
     for (size_t i=0; i<mObjectsSize; i++) {
         const flat_binder_object* flat
             = reinterpret_cast<const flat_binder_object*>(mData + mObjects[i]);
-        if (flat->type == BINDER_TYPE_FD) {
+        if (flat->hdr.type == BINDER_TYPE_FD) {
             hasFds = true;
             break;
         }
diff --git a/ProcessState.cpp b/ProcessState.cpp
index e4e1a12..37e3611 100644
--- a/ProcessState.cpp
+++ b/ProcessState.cpp
@@ -18,10 +18,10 @@
 
 #include <hwbinder/ProcessState.h>
 
+#include <cutils/atomic.h>
 #include <hwbinder/BpHwBinder.h>
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/binder_kernel.h>
-#include <utils/Atomic.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
@@ -39,7 +39,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
+#define DEFAULT_BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
 #define DEFAULT_MAX_BINDER_THREADS 0
 
 // -------------------------------------------------------------------------
@@ -71,7 +71,7 @@
     if (gProcess != NULL) {
         return gProcess;
     }
-    gProcess = new ProcessState;
+    gProcess = new ProcessState(DEFAULT_BINDER_VM_SIZE);
     return gProcess;
 }
 
@@ -80,6 +80,18 @@
     return gProcess;
 }
 
+sp<ProcessState> ProcessState::initWithMmapSize(size_t mmap_size) {
+    Mutex::Autolock _l(gProcessMutex);
+    if (gProcess != NULL) {
+        LOG_ALWAYS_FATAL_IF(mmap_size != gProcess->getMmapSize(),
+                "ProcessState already initialized with a different mmap size.");
+        return gProcess;
+    }
+
+    gProcess = new ProcessState(mmap_size);
+    return gProcess;
+}
+
 void ProcessState::setContextObject(const sp<IBinder>& object)
 {
     setContextObject(object, String16("default"));
@@ -208,6 +220,10 @@
     return count;
 }
 
+size_t ProcessState::getMmapSize() {
+    return mMmapSize;
+}
+
 ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
 {
     const size_t N=mHandleToObject.size();
@@ -333,6 +349,10 @@
     return result;
 }
 
+size_t ProcessState::getMaxThreads() {
+    return mMaxThreads;
+}
+
 void ProcessState::giveThreadPoolName() {
     androidSetThreadName( makeBinderThreadName().string() );
 }
@@ -364,7 +384,7 @@
     return fd;
 }
 
-ProcessState::ProcessState()
+ProcessState::ProcessState(size_t mmap_size)
     : mDriverFD(open_driver())
     , mVMStart(MAP_FAILED)
     , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
@@ -378,10 +398,11 @@
     , mThreadPoolStarted(false)
     , mSpawnThreadOnStart(true)
     , mThreadPoolSeq(1)
+    , mMmapSize(mmap_size)
 {
     if (mDriverFD >= 0) {
         // mmap the binder, providing a chunk of virtual address space to receive transactions.
-        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
+        mVMStart = mmap(0, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
         if (mVMStart == MAP_FAILED) {
             // *sigh*
             ALOGE("Using /dev/hwbinder failed: unable to mmap transaction memory.\n");
@@ -398,7 +419,7 @@
 {
     if (mDriverFD >= 0) {
         if (mVMStart != MAP_FAILED) {
-            munmap(mVMStart, BINDER_VM_SIZE);
+            munmap(mVMStart, mMmapSize);
         }
         close(mDriverFD);
     }
diff --git a/Static.cpp b/Static.cpp
index c63e503..a84f811 100644
--- a/Static.cpp
+++ b/Static.cpp
@@ -73,7 +73,7 @@
 
 // ------------ ProcessState.cpp
 
-Mutex gProcessMutex;
+Mutex& gProcessMutex = *new Mutex;
 sp<ProcessState> gProcess;
 
 class LibHwbinderIPCtStatics
diff --git a/include/hwbinder/IInterface.h b/include/hwbinder/IInterface.h
index 7ed6b42..17cbae9 100644
--- a/include/hwbinder/IInterface.h
+++ b/include/hwbinder/IInterface.h
@@ -38,23 +38,6 @@
 // ----------------------------------------------------------------------
 
 template<typename INTERFACE>
-class BnInterface : public INTERFACE, public IInterface, public BHwBinder
-{
-public:
-                                BnInterface(const sp<INTERFACE>& impl);
-protected:
-    const sp<INTERFACE>         mImpl;
-    virtual IBinder*            onAsBinder();
-};
-
-template<typename INTERFACE>
-inline BnInterface<INTERFACE>::BnInterface(
-        const sp<INTERFACE>& impl) : mImpl(impl)
-{
-}
-// ----------------------------------------------------------------------
-
-template<typename INTERFACE>
 class BpInterface : public INTERFACE, public IInterface, public BpHwRefBase
 {
 public:
@@ -67,11 +50,6 @@
 // ----------------------------------------------------------------------
 // No user-serviceable parts after this...
 
-template<typename INTERFACE>
-IBinder* BnInterface<INTERFACE>::onAsBinder()
-{
-    return this;
-}
 
 template<typename INTERFACE>
 inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
diff --git a/include/hwbinder/IPCThreadState.h b/include/hwbinder/IPCThreadState.h
index a3224c3..32eea8c 100644
--- a/include/hwbinder/IPCThreadState.h
+++ b/include/hwbinder/IPCThreadState.h
@@ -71,9 +71,9 @@
                                          uint32_t code, const Parcel& data,
                                          Parcel* reply, uint32_t flags);
 
-            void                incStrongHandle(int32_t handle);
+            void                incStrongHandle(int32_t handle, BpHwBinder *proxy);
             void                decStrongHandle(int32_t handle);
-            void                incWeakHandle(int32_t handle);
+            void                incWeakHandle(int32_t handle, BpHwBinder *proxy);
             void                decWeakHandle(int32_t handle);
             status_t            attemptIncStrongHandle(int32_t handle);
     static  void                expungeHandle(int32_t handle, IBinder* binder);
@@ -97,6 +97,10 @@
 
             // Service manager registration
             void                setTheContextObject(sp<BHwBinder> obj);
+
+            bool                isLooperThread();
+            bool                isOnlyBinderThread();
+
 private:
                                 IPCThreadState();
                                 ~IPCThreadState();
@@ -114,6 +118,7 @@
             status_t            getAndExecuteCommand();
             status_t            executeCommand(int32_t command);
             void                processPendingDerefs();
+            void                processPostWriteDerefs();
 
             void                clearCaller();
 
@@ -127,7 +132,8 @@
     const   pid_t               mMyThreadId;
             Vector<BHwBinder*>    mPendingStrongDerefs;
             Vector<RefBase::weakref_type*> mPendingWeakDerefs;
-
+            Vector<RefBase*>    mPostWriteStrongDerefs;
+            Vector<RefBase::weakref_type*> mPostWriteWeakDerefs;
             Parcel              mIn;
             Parcel              mOut;
             status_t            mLastError;
@@ -137,6 +143,8 @@
             int32_t             mStrictModePolicy;
             int32_t             mLastTransactionBinderFlags;
             sp<BHwBinder>         mContextObject;
+            bool                mIsLooper;
+            bool mIsPollingThread;
 };
 
 }; // namespace hardware
diff --git a/include/hwbinder/Parcel.h b/include/hwbinder/Parcel.h
index debffa3..f6e45d5 100644
--- a/include/hwbinder/Parcel.h
+++ b/include/hwbinder/Parcel.h
@@ -20,7 +20,6 @@
 #include <string>
 #include <vector>
 
-#include <android-base/unique_fd.h>
 #include <cutils/native_handle.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
diff --git a/include/hwbinder/ProcessState.h b/include/hwbinder/ProcessState.h
index 5441b75..2f72059 100644
--- a/include/hwbinder/ProcessState.h
+++ b/include/hwbinder/ProcessState.h
@@ -37,6 +37,8 @@
 public:
     static  sp<ProcessState>    self();
     static  sp<ProcessState>    selfOrNull();
+    // Note: don't call self() or selfOrNull() before initWithMmapSize()
+    static  sp<ProcessState>    initWithMmapSize(size_t mmapSize); // size in bytes
 
             void                setContextObject(const sp<IBinder>& object);
             sp<IBinder>         getContextObject(const sp<IBinder>& caller);
@@ -64,14 +66,15 @@
             void                spawnPooledThread(bool isMain);
 
             status_t            setThreadPoolConfiguration(size_t maxThreads, bool callerJoinsPool);
+            size_t              getMaxThreads();
             void                giveThreadPoolName();
 
             ssize_t             getKernelReferences(size_t count, uintptr_t* buf);
-
+            size_t              getMmapSize();
 private:
     friend class IPCThreadState;
 
-                                ProcessState();
+                                ProcessState(size_t mmap_size);
                                 ~ProcessState();
 
                                 ProcessState(const ProcessState& o);
@@ -114,6 +117,7 @@
             bool                mThreadPoolStarted;
             bool                mSpawnThreadOnStart;
     volatile int32_t            mThreadPoolSeq;
+            size_t              mMmapSize;
 };
 
 }; // namespace hardware
diff --git a/include/hwbinder/Static.h b/include/hwbinder/Static.h
index 99821ca..4b84c89 100644
--- a/include/hwbinder/Static.h
+++ b/include/hwbinder/Static.h
@@ -29,7 +29,7 @@
 extern Vector<int32_t> gTextBuffers;
 
 // For ProcessState.cpp
-extern Mutex gProcessMutex;
+extern Mutex& gProcessMutex;
 extern sp<ProcessState> gProcess;
 
 }   // namespace hardware
diff --git a/include/hwbinder/binder_kernel.h b/include/hwbinder/binder_kernel.h
index 48da770..27a0595 100644
--- a/include/hwbinder/binder_kernel.h
+++ b/include/hwbinder/binder_kernel.h
@@ -21,89 +21,13 @@
 
 /**
  * This file exists because the uapi kernel headers in bionic are built
- * from upstream kernel headers only, and the hwbinder kernel changes
- * haven't made it upstream yet. Therefore, the modifications to the
+ * from upstream kernel headers only, and not all of the hwbinder kernel changes
+ * have made it upstream yet. Therefore, the modifications to the
  * binder header are added locally in this file.
  */
 
 enum {
-	BINDER_TYPE_PTR		= B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE),
-	BINDER_TYPE_FDA		= B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE),
-};
-
-/* This header is used in all binder objects that are fixed
- * up by the kernel driver */
-struct binder_object_header {
-	__u32        type;
-};
-
-struct binder_fd_object {
-	struct binder_object_header	hdr;
-	/* FD objects used to be represented in flat_binder_object as well,
-	 * so we're using pads here to remain compatibile to existing userspace
-	 * clients.
-	 */
-	__u32				pad_flags;
-	union {
-		binder_uintptr_t	pad_binder;
-		__u32			fd;
-	};
-
-	binder_uintptr_t		cookie;
-};
-
-/* A binder_buffer object represents an object that the
- * binder kernel driver copies verbatim to the target
- * address space. A buffer itself may be pointed to from
- * within another buffer, meaning that the pointer inside
- * that other buffer needs to be fixed up as well. This
- * can be done by specifying the parent buffer, and the
- * byte offset at which the pointer lives in that buffer.
- */
-struct binder_buffer_object {
-	struct binder_object_header	hdr;
-	__u32				flags;
-
-	union {
-		struct {
-			binder_uintptr_t   buffer; /* Pointer to buffer data */
-			binder_size_t      length; /* Length of the buffer data */
-		};
-		struct {
-			binder_size_t      child;        /* index of child in objects array */
-			binder_size_t      child_offset; /* byte offset in child buffer */
-		};
-	};
-	binder_size_t			parent; /* index of parent in objects array */
-	binder_size_t			parent_offset; /* byte offset of pointer in parent buffer */
-};
-
-enum {
-	BINDER_BUFFER_HAS_PARENT   = 1U << 0,
-	BINDER_BUFFER_REF          = 1U << 1,
-};
-
-/* A binder_fd_array object represents an array of file
- * descriptors embedded in a binder_buffer_object. The
- * kernel driver will fix up all file descriptors in
- * the parent buffer specified by parent and parent_offset
- */
-struct binder_fd_array_object {
-	struct binder_object_header	hdr;
-	__u32			_pad; /* hdr is 4 bytes, ensure 8-byte alignment of next fields */
-	binder_size_t		num_fds;
-	binder_size_t		parent; /* index of parent in objects array */
-	binder_size_t		parent_offset; /* offset of pointer in parent */
-};
-
-struct binder_transaction_data_sg {
-    binder_transaction_data    tr; /* regular transaction data */
-    binder_size_t              buffers_size; /* number of bytes of SG buffers */
-};
-
-enum {
-	BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg),
-	BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg),
+	BINDER_BUFFER_FLAG_REF          = 1U << 1,
 };
 
 enum {
@@ -125,13 +49,4 @@
                               struct binder_transaction_data_secctx),
 };
 
-struct binder_node_debug_info {
-	binder_uintptr_t ptr;
-	binder_uintptr_t cookie;
-	__u32 has_strong_ref;
-	__u32 has_weak_ref;
-};
-
-#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
-
 #endif // ANDROID_HARDWARE_BINDER_KERNEL_H
diff --git a/vts/OWNERS b/vts/OWNERS
index db577ad..6a26ae7 100644
--- a/vts/OWNERS
+++ b/vts/OWNERS
@@ -1,3 +1,2 @@
-set noparent
 yim@google.com
 zhuoyao@google.com
diff --git a/vts/performance/Android.bp b/vts/performance/Android.bp
new file mode 100644
index 0000000..c5fa2a0
--- /dev/null
+++ b/vts/performance/Android.bp
@@ -0,0 +1,80 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_defaults {
+    name: "libhwbinder_test_defaults",
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+}
+
+cc_benchmark {
+    name: "libhwbinder_benchmark",
+    defaults: ["libhwbinder_test_defaults"],
+    srcs: ["Benchmark.cpp"],
+    static_libs: ["android.hardware.tests.libhwbinder@1.0"],
+    required: ["android.hardware.tests.libhwbinder@1.0-impl"],
+}
+
+// build for benchmark test based on binder.
+cc_benchmark {
+    name: "libbinder_benchmark",
+
+    srcs: ["Benchmark_binder.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "android.hardware.tests.libbinder",
+    ],
+}
+
+// build for throughput benchmark test for hwbinder.
+cc_test {
+    name: "hwbinderThroughputTest",
+    defaults: ["libhwbinder_test_defaults"],
+    srcs: ["Benchmark_throughput.cpp"],
+    static_libs: ["android.hardware.tests.libhwbinder@1.0"],
+    required: ["android.hardware.tests.libhwbinder@1.0-impl"],
+}
+
+// build for latency benchmark test for hwbinder.
+cc_test {
+    name: "libhwbinder_latency",
+    defaults: ["libhwbinder_test_defaults"],
+
+    srcs: [
+        "Latency.cpp",
+        "PerfTest.cpp",
+    ],
+
+    static_libs: ["android.hardware.tests.libhwbinder@1.0"],
+
+    required: ["android.hardware.tests.libhwbinder@1.0-impl"],
+}
diff --git a/vts/performance/Android.mk b/vts/performance/Android.mk
deleted file mode 100644
index b238715..0000000
--- a/vts/performance/Android.mk
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libhwbinder_benchmark
-LOCAL_MODULE_STEM_64 := libhwbinder_benchmark64
-LOCAL_MODULE_STEM_32 := libhwbinder_benchmark32
-
-LOCAL_MODULE_TAGS := eng tests
-
-LOCAL_SRC_FILES := Benchmark.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libhwbinder \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    android.hardware.tests.libhwbinder@1.0
-LOCAL_REQUIRED_MODULES := android.hardware.tests.libhwbinder@1.0-impl
-
-LOCAL_MULTILIB := both
-
-include $(BUILD_NATIVE_BENCHMARK)
-
-
-# build for benchmark test based on binder.
-include $(CLEAR_VARS)
-LOCAL_MODULE := libbinder_benchmark
-LOCAL_MODULE_STEM_64 := libbinder_benchmark64
-LOCAL_MODULE_STEM_32 := libbinder_benchmark32
-
-LOCAL_MODULE_TAGS := eng tests
-
-LOCAL_SRC_FILES := Benchmark_binder.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libbinder \
-    libutils \
-    android.hardware.tests.libbinder
-
-LOCAL_MULTILIB := both
-
-include $(BUILD_NATIVE_BENCHMARK)
-
-# build for throughput benchmark test for hwbinder.
-include $(CLEAR_VARS)
-LOCAL_MODULE := hwbinderThroughputTest
-
-LOCAL_MODULE_TAGS := eng tests
-
-LOCAL_SRC_FILES := Benchmark_throughput.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libhwbinder \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    android.hardware.tests.libhwbinder@1.0
-
-LOCAL_REQUIRED_MODULES := android.hardware.tests.libhwbinder@1.0-impl
-LOCAL_C_INCLUDES := system/libhwbinder/include
-
-LOCAL_MULTILIB := both
-include $(BUILD_NATIVE_TEST)
-
-# build for latency benchmark test for hwbinder.
-include $(CLEAR_VARS)
-LOCAL_MODULE := libhwbinder_latency
-
-LOCAL_MODULE_TAGS := eng tests
-
-LOCAL_SRC_FILES := Latency.cpp PerfTest.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libhwbinder \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    android.hardware.tests.libhwbinder@1.0
-
-LOCAL_REQUIRED_MODULES := android.hardware.tests.libhwbinder@1.0-impl
-LOCAL_C_INCLUDES := system/libhwbinder/include
-
-LOCAL_MULTILIB := both
-include $(BUILD_NATIVE_TEST)
diff --git a/vts/performance/Benchmark.cpp b/vts/performance/Benchmark.cpp
index 4068903..e7d75cd 100644
--- a/vts/performance/Benchmark.cpp
+++ b/vts/performance/Benchmark.cpp
@@ -136,7 +136,6 @@
         // Child, start benchmarks
         ::benchmark::RunSpecifiedBenchmarks();
     } else {
-        int stat;
         startServer();
         while (true) {
             int stat, retval;
diff --git a/vts/performance/Benchmark_binder.cpp b/vts/performance/Benchmark_binder.cpp
index 1f8c1db..1458fc9 100644
--- a/vts/performance/Benchmark_binder.cpp
+++ b/vts/performance/Benchmark_binder.cpp
@@ -36,7 +36,6 @@
 
 // libbinder:
 using android::getService;
-using android::BnInterface;
 using android::defaultServiceManager;
 using android::ProcessState;
 using android::binder::Status;
@@ -63,6 +62,8 @@
 
 bool startServer() {
     BenchmarkServiceAidl *service = new BenchmarkServiceAidl();
+    // Tells the kernel to spawn zero threads, but startThreadPool() below will still spawn one.
+    ProcessState::self()->setThreadPoolMaxThreadCount(0);
     defaultServiceManager()->addService(String16(kServiceName),
                                         service);
     ProcessState::self()->startThreadPool();
@@ -99,7 +100,6 @@
         // Child, start benchmarks
         ::benchmark::RunSpecifiedBenchmarks();
     } else {
-        int stat;
         startServer();
         while (true) {
             int stat, retval;