DO NOT MERGE - Merge pie-platform-release (PPRL.190705.004) into master

Bug: 136196576
Change-Id: I2ecaea1e2e59807dbf153c9ec0d2fccbec27fc88
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index 9b3f9d9..0000000
--- a/.clang-format
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# 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.
-#
-
-BasedOnStyle: Google
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 100
-TabWidth: 4
-UseTab: Never
-IndentWidth: 4
diff --git a/Android.bp b/Android.bp
index 4214d85..47b3b3f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,10 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-subdirs = [
-    "vts/performance",
-]
-
 cc_defaults {
     name: "libhwbinder_defaults",
     shared_libs: [
@@ -23,6 +19,7 @@
         "liblog",
         "libcutils",
         "libutils",
+        "libbinderthreadstate",
     ],
     export_shared_lib_headers: [
         "libbase",
@@ -31,6 +28,7 @@
     export_include_dirs: ["include"],
     include_dirs: ["frameworks/native/include"],
 
+    recovery_available: true,
     vendor_available: true,
     vndk: {
         enabled: true,
@@ -70,7 +68,7 @@
     defaults: [
         "libhwbinder_defaults",
         "hwbinder_pgo",
-        "hwbinder_lto"
+        "hwbinder_lto",
     ],
 }
 
@@ -94,6 +92,7 @@
         enable_profile_use: true,
     },
 }
+
 // Provide lto property to build hwbinder with LTO
 cc_defaults {
     name: "hwbinder_lto",
diff --git a/Binder.cpp b/Binder.cpp
index 147c7ca..72884f0 100644
--- a/Binder.cpp
+++ b/Binder.cpp
@@ -43,12 +43,12 @@
 
 BHwBinder* IBinder::localBinder()
 {
-    return NULL;
+    return nullptr;
 }
 
 BpHwBinder* IBinder::remoteBinder()
 {
-    return NULL;
+    return nullptr;
 }
 
 bool IBinder::checkSubclass(const void* /*subclassID*/) const
@@ -116,7 +116,7 @@
             err = onTransact(code, data, reply, flags,
                     [&](auto &replyParcel) {
                         replyParcel.setDataPosition(0);
-                        if (callback != NULL) {
+                        if (callback != nullptr) {
                             callback(replyParcel);
                         }
                     });
@@ -154,7 +154,7 @@
 void* BHwBinder::findObject(const void* objectID) const
 {
     Extras* e = mExtras.load(std::memory_order_acquire);
-    if (!e) return NULL;
+    if (!e) return nullptr;
 
     AutoMutex _l(e->mLock);
     return e->mObjects.find(objectID);
@@ -217,7 +217,7 @@
 };
 
 BpHwRefBase::BpHwRefBase(const sp<IBinder>& o)
-    : mRemote(o.get()), mRefs(NULL), mState(0)
+    : mRemote(o.get()), mRefs(nullptr), mState(0)
 {
     if (mRemote) {
         mRemote->incStrong(this);           // Removed on first IncStrong().
diff --git a/BpHwBinder.cpp b/BpHwBinder.cpp
index 90b3c6f..7c6e3ec 100644
--- a/BpHwBinder.cpp
+++ b/BpHwBinder.cpp
@@ -62,7 +62,7 @@
 void* BpHwBinder::ObjectManager::find(const void* objectID) const
 {
     const ssize_t i = mObjects.indexOfKey(objectID);
-    if (i < 0) return NULL;
+    if (i < 0) return nullptr;
     return mObjects.valueAt(i).object;
 }
 
@@ -77,7 +77,7 @@
     ALOGV("Killing %zu objects in manager %p", N, this);
     for (size_t i=0; i<N; i++) {
         const entry_t& e = mObjects.valueAt(i);
-        if (e.func != NULL) {
+        if (e.func != nullptr) {
             e.func(mObjects.keyAt(i), e.object, e.cleanupCookie);
         }
     }
@@ -91,7 +91,7 @@
     : mHandle(handle)
     , mAlive(1)
     , mObitsSent(0)
-    , mObituaries(NULL)
+    , mObituaries(nullptr)
 {
     ALOGV("Creating BpHwBinder %p handle %d\n", this, mHandle);
 
@@ -100,12 +100,17 @@
 }
 
 status_t BpHwBinder::transact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags, TransactCallback /*callback*/)
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags, TransactCallback callback)
 {
     // Once a binder has died, it will never come back to life.
     if (mAlive) {
         status_t status = IPCThreadState::self()->transact(
             mHandle, code, data, reply, flags);
+
+        if (status == ::android::OK && callback != nullptr) {
+            callback(*reply);
+        }
+
         if (status == DEAD_OBJECT) mAlive = 0;
         return status;
     }
@@ -121,7 +126,7 @@
     ob.cookie = cookie;
     ob.flags = flags;
 
-    LOG_ALWAYS_FATAL_IF(recipient == NULL,
+    LOG_ALWAYS_FATAL_IF(recipient == nullptr,
                         "linkToDeath(): recipient must be non-NULL");
 
     {
@@ -161,9 +166,9 @@
     for (size_t i=0; i<N; i++) {
         const Obituary& obit = mObituaries->itemAt(i);
         if ((obit.recipient == recipient
-                    || (recipient == NULL && obit.cookie == cookie))
+                    || (recipient == nullptr && obit.cookie == cookie))
                 && obit.flags == flags) {
-            if (outRecipient != NULL) {
+            if (outRecipient != nullptr) {
                 *outRecipient = mObituaries->itemAt(i).recipient;
             }
             mObituaries->removeAt(i);
@@ -173,7 +178,7 @@
                 self->clearDeathNotification(mHandle, this);
                 self->flushCommands();
                 delete mObituaries;
-                mObituaries = NULL;
+                mObituaries = nullptr;
             }
             return NO_ERROR;
         }
@@ -192,12 +197,12 @@
 
     mLock.lock();
     Vector<Obituary>* obits = mObituaries;
-    if(obits != NULL) {
+    if(obits != nullptr) {
         ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
         IPCThreadState* self = IPCThreadState::self();
         self->clearDeathNotification(mHandle, this);
         self->flushCommands();
-        mObituaries = NULL;
+        mObituaries = nullptr;
     }
     mObitsSent = 1;
     mLock.unlock();
@@ -205,7 +210,7 @@
     ALOGV("Reporting death of proxy %p for %zu recipients\n",
         this, obits ? obits->size() : 0U);
 
-    if (obits != NULL) {
+    if (obits != nullptr) {
         const size_t N = obits->size();
         for (size_t i=0; i<N; i++) {
             reportOneDeath(obits->itemAt(i));
@@ -215,11 +220,18 @@
     }
 }
 
+// Returns the strong refcount on the object this proxy points to, or
+// -1 in case of failure.
+ssize_t BpHwBinder::getNodeStrongRefCount()
+{
+    return ProcessState::self()->getStrongRefCountForNodeByHandle(mHandle);
+}
+
 void BpHwBinder::reportOneDeath(const Obituary& obit)
 {
     sp<DeathRecipient> recipient = obit.recipient.promote();
     ALOGV("Reporting death to recipient: %p\n", recipient.get());
-    if (recipient == NULL) return;
+    if (recipient == nullptr) return;
 
     recipient->binderDied(this);
 }
@@ -257,21 +269,6 @@
 
     IPCThreadState* ipc = IPCThreadState::self();
 
-    mLock.lock();
-    Vector<Obituary>* obits = mObituaries;
-    if(obits != NULL) {
-        if (ipc) ipc->clearDeathNotification(mHandle, this);
-        mObituaries = NULL;
-    }
-    mLock.unlock();
-
-    if (obits != NULL) {
-        // XXX Should we tell any remaining DeathRecipient
-        // objects that the last strong ref has gone away, so they
-        // are no longer linked?
-        delete obits;
-    }
-
     if (ipc) {
         ipc->expungeHandle(mHandle, this);
         ipc->decWeakHandle(mHandle);
@@ -296,6 +293,26 @@
         ipc->decStrongHandle(mHandle);
         ipc->flushCommands();
     }
+
+    mLock.lock();
+    Vector<Obituary>* obits = mObituaries;
+    if(obits != nullptr) {
+        if (!obits->isEmpty()) {
+            ALOGI("onLastStrongRef automatically unlinking death recipients");
+        }
+
+        if (ipc) ipc->clearDeathNotification(mHandle, this);
+        mObituaries = nullptr;
+    }
+    mLock.unlock();
+
+    if (obits != nullptr) {
+        // XXX Should we tell any remaining DeathRecipient
+        // objects that the last strong ref has gone away, so they
+        // are no longer linked?
+        delete obits;
+        obits = nullptr;
+    }
 }
 
 bool BpHwBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
diff --git a/BufferedTextOutput.cpp b/BufferedTextOutput.cpp
index 9bddde5..3c7db8b 100644
--- a/BufferedTextOutput.cpp
+++ b/BufferedTextOutput.cpp
@@ -27,6 +27,7 @@
 
 #include <hwbinder/Static.h>
 
+#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -39,7 +40,7 @@
 {
     explicit BufferState(int32_t _seq)
         : seq(_seq)
-        , buffer(NULL)
+        , buffer(nullptr)
         , bufferPos(0)
         , bufferSize(0)
         , atFront(true)
@@ -91,7 +92,7 @@
     Vector<sp<BufferedTextOutput::BufferState> > states;
 };
 
-static mutex_t          gMutex;
+static pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER;
 
 static thread_store_t   tls;
 
@@ -117,7 +118,7 @@
 {
     int32_t res = -1;
 
-    mutex_lock(&gMutex);
+    pthread_mutex_lock(&gMutex);
 
     if (gFreeBufferIndex >= 0) {
         res = gFreeBufferIndex;
@@ -129,17 +130,17 @@
         gTextBuffers.add(-1);
     }
 
-    mutex_unlock(&gMutex);
+    pthread_mutex_unlock(&gMutex);
 
     return res;
 }
 
 static void freeBufferIndex(int32_t idx)
 {
-    mutex_lock(&gMutex);
+    pthread_mutex_lock(&gMutex);
     gTextBuffers.editItemAt(idx) = gFreeBufferIndex;
     gFreeBufferIndex = idx;
-    mutex_unlock(&gMutex);
+    pthread_mutex_unlock(&gMutex);
 }
 
 // ---------------------------------------------------------------------------
@@ -265,13 +266,13 @@
     if ((mFlags&MULTITHREADED) != 0) {
         ThreadState* ts = getThreadState();
         if (ts) {
-            while (ts->states.size() <= (size_t)mIndex) ts->states.add(NULL);
+            while (ts->states.size() <= (size_t)mIndex) ts->states.add(nullptr);
             BufferState* bs = ts->states[mIndex].get();
-            if (bs != NULL && bs->seq == mSeq) return bs;
+            if (bs != nullptr && bs->seq == mSeq) return bs;
 
             ts->states.editItemAt(mIndex) = new BufferState(mIndex);
             bs = ts->states[mIndex].get();
-            if (bs != NULL) return bs;
+            if (bs != nullptr) return bs;
         }
     }
 
diff --git a/Debug.cpp b/Debug.cpp
index d304d21..38e3a3f 100644
--- a/Debug.cpp
+++ b/Debug.cpp
@@ -166,13 +166,13 @@
         else if (bytesPerLine >= 8) alignment = 2;
         else alignment = 1;
     }
-    if (func == NULL) func = defaultPrintFunc;
+    if (func == nullptr) func = defaultPrintFunc;
 
     size_t offset;
 
     unsigned char *pos = (unsigned char *)buf;
 
-    if (pos == NULL) {
+    if (pos == nullptr) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         func(cookie, "(NULL)");
         return;
@@ -302,7 +302,7 @@
 
 ssize_t getHWBinderKernelReferences(size_t count, uintptr_t* buf) {
     sp<ProcessState> proc = ProcessState::selfOrNull();
-    if (proc.get() == NULL) {
+    if (proc.get() == nullptr) {
         return 0;
     }
 
diff --git a/IInterface.cpp b/IInterface.cpp
index 01866e6..3545325 100644
--- a/IInterface.cpp
+++ b/IInterface.cpp
@@ -33,14 +33,14 @@
 // static
 sp<IBinder> IInterface::asBinder(const IInterface* iface)
 {
-    if (iface == NULL) return NULL;
+    if (iface == nullptr) return nullptr;
     return const_cast<IInterface*>(iface)->onAsBinder();
 }
 
 // static
 sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
 {
-    if (iface == NULL) return NULL;
+    if (iface == nullptr) return nullptr;
     return iface->onAsBinder();
 }
 
diff --git a/IPCThreadState.cpp b/IPCThreadState.cpp
index b36838e..a87b5f4 100644
--- a/IPCThreadState.cpp
+++ b/IPCThreadState.cpp
@@ -17,12 +17,15 @@
 #define LOG_TAG "hw-IPCThreadState"
 
 #include <hwbinder/IPCThreadState.h>
+#include <binderthreadstate/IPCThreadStateBase.h>
 
 #include <hwbinder/Binder.h>
 #include <hwbinder/BpHwBinder.h>
 #include <hwbinder/TextOutput.h>
 #include <hwbinder/binder_kernel.h>
 
+#include <android-base/macros.h>
+#include <utils/CallStack.h>
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
 #include <utils/threads.h>
@@ -30,6 +33,7 @@
 #include <private/binder/binder_module.h>
 #include <hwbinder/Static.h>
 
+#include <atomic>
 #include <errno.h>
 #include <inttypes.h>
 #include <pthread.h>
@@ -109,8 +113,9 @@
     "BC_DEAD_BINDER_DONE"
 };
 
-static const char* getReturnString(size_t idx)
+static const char* getReturnString(uint32_t cmd)
 {
+    size_t idx = cmd & _IOC_NRMASK;
     if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[0]))
         return kReturnStrings[idx];
     else
@@ -272,14 +277,13 @@
 }
 
 static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
-static bool gHaveTLS = false;
+static std::atomic<bool> gHaveTLS = false;
 static pthread_key_t gTLS = 0;
-static bool gShutdown = false;
-static bool gDisableBackgroundScheduling = false;
+static std::atomic<bool> gShutdown = false;
 
 IPCThreadState* IPCThreadState::self()
 {
-    if (gHaveTLS) {
+    if (gHaveTLS.load(std::memory_order_acquire)) {
 restart:
         const pthread_key_t k = gTLS;
         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
@@ -287,21 +291,22 @@
         return new IPCThreadState;
     }
 
-    if (gShutdown) {
+    // Racey, heuristic test for simultaneous shutdown.
+    if (gShutdown.load(std::memory_order_relaxed)) {
         ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
-        return NULL;
+        return nullptr;
     }
 
     pthread_mutex_lock(&gTLSMutex);
-    if (!gHaveTLS) {
+    if (!gHaveTLS.load(std::memory_order_relaxed)) {
         int key_create_value = pthread_key_create(&gTLS, threadDestructor);
         if (key_create_value != 0) {
             pthread_mutex_unlock(&gTLSMutex);
             ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
                     strerror(key_create_value));
-            return NULL;
+            return nullptr;
         }
-        gHaveTLS = true;
+        gHaveTLS.store(true, std::memory_order_release);
     }
     pthread_mutex_unlock(&gTLSMutex);
     goto restart;
@@ -309,35 +314,30 @@
 
 IPCThreadState* IPCThreadState::selfOrNull()
 {
-    if (gHaveTLS) {
+    if (gHaveTLS.load(std::memory_order_acquire)) {
         const pthread_key_t k = gTLS;
         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
         return st;
     }
-    return NULL;
+    return nullptr;
 }
 
 void IPCThreadState::shutdown()
 {
-    gShutdown = true;
+    gShutdown.store(true, std::memory_order_relaxed);
 
-    if (gHaveTLS) {
+    if (gHaveTLS.load(std::memory_order_acquire)) {
         // XXX Need to wait for all thread pool threads to exit!
         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS);
         if (st) {
             delete st;
-            pthread_setspecific(gTLS, NULL);
+            pthread_setspecific(gTLS, nullptr);
         }
         pthread_key_delete(gTLS);
-        gHaveTLS = false;
+        gHaveTLS.store(false, std::memory_order_release);
     }
 }
 
-void IPCThreadState::disableBackgroundScheduling(bool disable)
-{
-    gDisableBackgroundScheduling = disable;
-}
-
 sp<ProcessState> IPCThreadState::process()
 {
     return mProcess;
@@ -478,6 +478,16 @@
         pthread_mutex_unlock(&mProcess->mThreadCountLock);
     }
 
+    if (UNLIKELY(!mPostCommandTasks.empty())) {
+        // make a copy in case the post transaction task makes a binder
+        // call and that other process calls back into us
+        std::vector<std::function<void(void)>> tasks = mPostCommandTasks;
+        mPostCommandTasks.clear();
+        for (const auto& func : tasks) {
+            func();
+        }
+    }
+
     return result;
 }
 
@@ -627,7 +637,7 @@
 
     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);
+    err = writeTransactionData(BC_TRANSACTION_SG, flags, handle, code, data, nullptr);
 
     if (err != NO_ERROR) {
         if (reply) reply->setError(err);
@@ -635,6 +645,16 @@
     }
 
     if ((flags & TF_ONE_WAY) == 0) {
+        if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
+            if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
+                ALOGE("Process making non-oneway call (code: %u) but is restricted.", code);
+                CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
+                    ANDROID_LOG_ERROR);
+            } else /* FATAL_IF_NOT_ONEWAY */ {
+                LOG_ALWAYS_FATAL("Process may not make oneway calls (code: %u).", code);
+            }
+        }
+
         #if 0
         if (code == 4) { // relayout
             ALOGI(">>>>>> CALLING transaction 4");
@@ -663,7 +683,7 @@
             else alog << "(none requested)" << endl;
         }
     } else {
-        err = waitForResponse(NULL, NULL);
+        err = waitForResponse(nullptr, nullptr);
     }
 
     return err;
@@ -712,10 +732,10 @@
     mOut.writeInt32(handle);
     status_t result = UNKNOWN_ERROR;
 
-    waitForResponse(NULL, &result);
+    waitForResponse(nullptr, &result);
 
 #if LOG_REFCOUNTS
-    printf("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n",
+    ALOGV("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n",
         handle, result == NO_ERROR ? "SUCCESS" : "FAILURE");
 #endif
 
@@ -730,7 +750,7 @@
 void IPCThreadState::expungeHandle(int32_t handle, IBinder* binder)
 {
 #if LOG_REFCOUNTS
-    printf("IPCThreadState::expungeHandle(%ld)\n", handle);
+    ALOGV("IPCThreadState::expungeHandle(%ld)\n", handle);
 #endif
     self()->mProcess->expungeHandle(handle, binder);  // NOLINT
 }
@@ -753,18 +773,17 @@
 
 IPCThreadState::IPCThreadState()
     : mProcess(ProcessState::self()),
-      mMyThreadId(gettid()),
       mStrictModePolicy(0),
       mLastTransactionBinderFlags(0),
       mIsLooper(false),
-      mIsPollingThread(false) {
+      mIsPollingThread(false),
+      mCallRestriction(mProcess->mCallRestriction) {
     pthread_setspecific(gTLS, this);
     clearCaller();
     mIn.setDataCapacity(256);
     mOut.setDataCapacity(256);
 
-    // TODO(b/67742352): remove this variable from the class
-    (void)mMyThreadId;
+    mIPCThreadStateBase = IPCThreadStateBase::self();
 }
 
 IPCThreadState::~IPCThreadState()
@@ -778,7 +797,7 @@
     err = writeTransactionData(BC_REPLY_SG, flags, -1, 0, reply, &statusBuffer);
     if (err < NO_ERROR) return err;
 
-    return waitForResponse(NULL, NULL);
+    return waitForResponse(nullptr, nullptr);
 }
 
 status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
@@ -814,7 +833,7 @@
 
         case BR_ACQUIRE_RESULT:
             {
-                ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
+                ALOG_ASSERT(acquireResult != nullptr, "Unexpected brACQUIRE_RESULT");
                 const int32_t result = mIn.readInt32();
                 if (!acquireResult) continue;
                 *acquireResult = result ? NO_ERROR : INVALID_OPERATION;
@@ -838,14 +857,14 @@
                             freeBuffer, this);
                     } else {
                         err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
-                        freeBuffer(NULL,
+                        freeBuffer(nullptr,
                             reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                             tr.data_size,
                             reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                             tr.offsets_size/sizeof(binder_size_t), this);
                     }
                 } else {
-                    freeBuffer(NULL,
+                    freeBuffer(nullptr,
                         reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                         tr.data_size,
                         reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
@@ -1011,9 +1030,11 @@
     return NO_ERROR;
 }
 
+sp<BHwBinder> the_context_object;
+
 void IPCThreadState::setTheContextObject(sp<BHwBinder> obj)
 {
-    mContextObject = obj;
+    the_context_object = obj;
 }
 
 bool IPCThreadState::isLooperThread()
@@ -1025,6 +1046,10 @@
     return (mIsLooper && mProcess->mMaxThreads <= 1) || mIsPollingThread;
 }
 
+void IPCThreadState::addPostCommandTask(const std::function<void(void)>& task) {
+    mPostCommandTasks.push_back(task);
+}
+
 status_t IPCThreadState::executeCommand(int32_t cmd)
 {
     BHwBinder* obj;
@@ -1109,7 +1134,7 @@
             binder_transaction_data_secctx tr_secctx;
             binder_transaction_data& tr = tr_secctx.transaction_data;
 
-            if (cmd == (int) BR_TRANSACTION_SEC_CTX) {
+            if (cmd == BR_TRANSACTION_SEC_CTX) {
                 result = mIn.read(&tr_secctx, sizeof(tr_secctx));
             } else {
                 result = mIn.read(&tr, sizeof(tr));
@@ -1120,6 +1145,9 @@
                 "Not enough command data for brTRANSACTION");
             if (result != NO_ERROR) break;
 
+            // Record the fact that we're in a hwbinder call
+            mIPCThreadStateBase->pushCurrentState(
+                IPCThreadStateBase::CallState::HWBINDER);
             Parcel buffer;
             buffer.ipcSetDataReference(
                 reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
@@ -1183,9 +1211,10 @@
                 }
 
             } else {
-                error = mContextObject->transact(tr.code, buffer, &reply, tr.flags, reply_callback);
+                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags, reply_callback);
             }
 
+            mIPCThreadStateBase->popCurrentState();
             if ((tr.flags & TF_ONE_WAY) == 0) {
                 if (!reply_sent) {
                     // Should have been a reply but there wasn't, so there
@@ -1246,7 +1275,7 @@
         break;
 
     default:
-        printf("*** BAD COMMAND %d received from Binder driver\n", cmd);
+        ALOGE("*** BAD COMMAND %d received from Binder driver\n", cmd);
         result = UNKNOWN_ERROR;
         break;
     }
@@ -1258,6 +1287,11 @@
     return result;
 }
 
+bool IPCThreadState::isServingCall() const
+{
+    return mIPCThreadStateBase->getCurrentBinderCallState() == IPCThreadStateBase::CallState::HWBINDER;
+}
+
 void IPCThreadState::threadDestructor(void *st)
 {
         IPCThreadState* const self = static_cast<IPCThreadState*>(st);
@@ -1282,8 +1316,8 @@
     IF_LOG_COMMANDS() {
         alog << "Writing BC_FREE_BUFFER for " << data << endl;
     }
-    ALOG_ASSERT(data != NULL, "Called with NULL data");
-    if (parcel != NULL) parcel->closeFileDescriptors();
+    ALOG_ASSERT(data != nullptr, "Called with NULL data");
+    if (parcel != nullptr) parcel->closeFileDescriptors();
     IPCThreadState* state = self();
     state->mOut.writeInt32(BC_FREE_BUFFER);
     state->mOut.writePointer((uintptr_t)data);
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
deleted file mode 100644
index 213c93a..0000000
--- a/PREUPLOAD.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[Options]
-ignore_merged_commits = true
-
-[Builtin Hooks]
-clang_format = true
diff --git a/Parcel.cpp b/Parcel.cpp
index 6e9bd1e..5142143 100644
--- a/Parcel.cpp
+++ b/Parcel.cpp
@@ -76,14 +76,6 @@
 // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER
 #define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
 
-// XXX This can be made public if we want to provide
-// support for typed data.
-struct small_flat_data
-{
-    uint32_t type;
-    uint32_t data;
-};
-
 namespace android {
 namespace hardware {
 
@@ -93,8 +85,6 @@
 
 static size_t gMaxFds = 0;
 
-static const size_t PARCEL_REF_CAP = 1024;
-
 void acquire_binder_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who)
 {
@@ -111,7 +101,7 @@
             return;
         case BINDER_TYPE_HANDLE: {
             const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
-            if (b != NULL) {
+            if (b != nullptr) {
                 LOG_REFS("Parcel %p acquiring reference on remote %p", who, b.get());
                 b->incStrong(who);
             }
@@ -119,7 +109,7 @@
         }
         case BINDER_TYPE_WEAK_HANDLE: {
             const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
-            if (b != NULL) b.get_refs()->incWeak(who);
+            if (b != nullptr) b.get_refs()->incWeak(who);
             return;
         }
     }
@@ -157,7 +147,7 @@
             return;
         case BINDER_TYPE_HANDLE: {
             const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
-            if (b != NULL) {
+            if (b != nullptr) {
                 LOG_REFS("Parcel %p releasing reference on remote %p", who, b.get());
                 b->decStrong(who);
             }
@@ -165,7 +155,7 @@
         }
         case BINDER_TYPE_WEAK_HANDLE: {
             const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
-            if (b != NULL) b.get_refs()->decWeak(who);
+            if (b != nullptr) b.get_refs()->decWeak(who);
             return;
         }
         case BINDER_TYPE_FD: {
@@ -198,11 +188,11 @@
 {
     flat_binder_object obj = {};
 
-    if (binder != NULL) {
+    if (binder != nullptr) {
         BHwBinder *local = binder->localBinder();
         if (!local) {
             BpHwBinder *proxy = binder->remoteBinder();
-            if (proxy == NULL) {
+            if (proxy == nullptr) {
                 ALOGE("null proxy");
             }
             const int32_t handle = proxy ? proxy->handle() : 0;
@@ -241,13 +231,13 @@
     flat_binder_object obj = {};
 
     obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    if (binder != NULL) {
+    if (binder != nullptr) {
         sp<IBinder> real = binder.promote();
-        if (real != NULL) {
+        if (real != nullptr) {
             IBinder *local = real->localBinder();
             if (!local) {
                 BpHwBinder *proxy = real->remoteBinder();
-                if (proxy == NULL) {
+                if (proxy == nullptr) {
                     ALOGE("null proxy");
                 }
                 const int32_t handle = proxy ? proxy->handle() : 0;
@@ -274,13 +264,13 @@
         obj.hdr.type = BINDER_TYPE_BINDER;
         obj.binder = 0;
         obj.cookie = 0;
-        return finish_flatten_binder(NULL, obj, out);
+        return finish_flatten_binder(nullptr, obj, out);
 
     } else {
         obj.hdr.type = BINDER_TYPE_BINDER;
         obj.binder = 0;
         obj.cookie = 0;
-        return finish_flatten_binder(NULL, obj, out);
+        return finish_flatten_binder(nullptr, obj, out);
     }
 }
 
@@ -300,7 +290,7 @@
         switch (flat->hdr.type) {
             case BINDER_TYPE_BINDER:
                 *out = reinterpret_cast<IBinder*>(flat->cookie);
-                return finish_unflatten_binder(NULL, *flat, in);
+                return finish_unflatten_binder(nullptr, *flat, in);
             case BINDER_TYPE_HANDLE:
                 *out = proc->getStrongProxyForHandle(flat->handle);
                 return finish_unflatten_binder(
@@ -319,16 +309,16 @@
         switch (flat->hdr.type) {
             case BINDER_TYPE_BINDER:
                 *out = reinterpret_cast<IBinder*>(flat->cookie);
-                return finish_unflatten_binder(NULL, *flat, in);
+                return finish_unflatten_binder(nullptr, *flat, in);
             case BINDER_TYPE_WEAK_BINDER:
                 if (flat->binder != 0) {
                     out->set_object_and_refs(
                         reinterpret_cast<IBinder*>(flat->cookie),
                         reinterpret_cast<RefBase::weakref_type*>(flat->binder));
                 } else {
-                    *out = NULL;
+                    *out = nullptr;
                 }
-                return finish_unflatten_binder(NULL, *flat, in);
+                return finish_unflatten_binder(nullptr, *flat, in);
             case BINDER_TYPE_HANDLE:
             case BINDER_TYPE_WEAK_HANDLE:
                 *out = proc->getWeakProxyForHandle(flat->handle);
@@ -339,17 +329,6 @@
     return BAD_TYPE;
 }
 
-/*
- * 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_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_FLAG_REF) == 0;
-}
-
 // ---------------------------------------------------------------------------
 
 Parcel::Parcel()
@@ -569,14 +548,14 @@
     if (len > INT32_MAX) {
         // don't accept size_t values which may have come from an
         // inadvertent conversion from a negative int.
-        return NULL;
+        return nullptr;
     }
 
     const size_t padded = pad_size(len);
 
     // sanity check for integer overflow
     if (mDataPos+padded < mDataPos) {
-        return NULL;
+        return nullptr;
     }
 
     if ((mDataPos+padded) <= mDataCapacity) {
@@ -607,7 +586,7 @@
 
     status_t err = growData(padded);
     if (err == NO_ERROR) goto restart_write;
-    return NULL;
+    return nullptr;
 }
 
 status_t Parcel::writeInt8(int8_t val)
@@ -705,7 +684,7 @@
 
 status_t Parcel::writeString16(const char16_t* str, size_t len)
 {
-    if (str == NULL) return writeInt32(-1);
+    if (str == nullptr) return writeInt32(-1);
 
     status_t err = writeInt32(len);
     if (err == NO_ERROR) {
@@ -789,7 +768,7 @@
         size_t newSize = ((mObjectsSize+2)*3)/2;
         if (newSize * sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY;   // overflow
         binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
-        if (objects == NULL) return NO_MEMORY;
+        if (objects == nullptr) return NO_MEMORY;
         mObjects = objects;
         mObjectsCapacity = newSize;
     }
@@ -802,19 +781,15 @@
 template status_t Parcel::writeObject<binder_buffer_object>(const binder_buffer_object& val);
 template status_t Parcel::writeObject<binder_fd_array_object>(const binder_fd_array_object& val);
 
-
-// TODO merge duplicated code in writeEmbeddedBuffer, writeEmbeddedReference, and writeEmbeddedNullReference
-// TODO merge duplicated code in writeBuffer, writeReference, and writeNullReference
-
 bool Parcel::validateBufferChild(size_t child_buffer_handle,
                                  size_t child_offset) const {
     if (child_buffer_handle >= mObjectsSize)
         return false;
     binder_buffer_object *child = reinterpret_cast<binder_buffer_object*>
             (mData + mObjects[child_buffer_handle]);
-    if (!isBuffer(*child) || child_offset > child->length) {
+    if (child->hdr.type != BINDER_TYPE_PTR || child_offset > child->length) {
         // Parent object not a buffer, or not large enough
-        LOG_BUFFER("writeEmbeddedReference found wierd child. "
+        LOG_BUFFER("writeEmbeddedReference found weird child. "
                    "child_offset = %zu, child->length = %zu",
                    child_offset, (size_t)child->length);
         return false;
@@ -828,7 +803,7 @@
         return false;
     binder_buffer_object *parent = reinterpret_cast<binder_buffer_object*>
             (mData + mObjects[parent_buffer_handle]);
-    if (!isBuffer(*parent) ||
+    if (parent->hdr.type != BINDER_TYPE_PTR ||
             sizeof(binder_uintptr_t) > parent->length ||
             parent_offset > parent->length - sizeof(binder_uintptr_t)) {
         // Parent object not a buffer, or not large enough
@@ -876,110 +851,6 @@
     return writeObject(obj);
 }
 
-status_t Parcel::incrementNumReferences() {
-    ++mNumRef;
-    LOG_BUFFER("incrementNumReferences: %zu", mNumRef);
-    return mNumRef <= PARCEL_REF_CAP ? OK : NO_MEMORY;
-}
-
-status_t Parcel::writeReference(size_t *handle,
-        size_t child_buffer_handle, size_t child_offset) {
-    LOG_BUFFER("writeReference(child = (%zu, %zu)) -> %zu",
-        child_buffer_handle, child_offset,
-        mObjectsSize);
-    status_t status = incrementNumReferences();
-    if (status != OK)
-        return status;
-    if (!validateBufferChild(child_buffer_handle, child_offset))
-        return BAD_VALUE;
-    binder_buffer_object obj {
-        .hdr = { .type = BINDER_TYPE_PTR },
-        .flags = BINDER_BUFFER_FLAG_REF,
-        // The current binder.h does not have child and child_offset names yet.
-        // Use the buffer and length parameters.
-        .buffer = child_buffer_handle,
-        .length = child_offset,
-    };
-    if (handle != nullptr)
-        // We use an index into mObjects as a handle
-        *handle = mObjectsSize;
-    return writeObject(obj);
-}
-
-/* Write an object that describes a pointer from parent to child.
- * Output the handle of that object in the size_t *handle variable. */
-status_t Parcel::writeEmbeddedReference(size_t *handle,
-    size_t child_buffer_handle, size_t child_offset,
-    size_t parent_buffer_handle, size_t parent_offset) {
-    LOG_BUFFER("writeEmbeddedReference(child = (%zu, %zu), parent = (%zu, %zu)) -> %zu",
-        child_buffer_handle, child_offset,
-        parent_buffer_handle, parent_offset,
-        mObjectsSize);
-    status_t status = incrementNumReferences();
-    if (status != OK)
-        return status;
-    // The current binder.h does not have child and child_offset names yet.
-    // Use the buffer and length parameters.
-    if (!validateBufferChild(child_buffer_handle, child_offset))
-        return BAD_VALUE;
-    if(!validateBufferParent(parent_buffer_handle, parent_offset))
-        return BAD_VALUE;
-    binder_buffer_object obj {
-        .hdr = { .type = BINDER_TYPE_PTR },
-        .flags = BINDER_BUFFER_FLAG_REF | BINDER_BUFFER_FLAG_HAS_PARENT,
-        .buffer = child_buffer_handle,
-        .length = child_offset,
-        .parent = parent_buffer_handle,
-        .parent_offset = parent_offset,
-    };
-    if (handle != nullptr) {
-        // We use an index into mObjects as a handle
-        *handle = mObjectsSize;
-    }
-    return writeObject(obj);
-}
-
-status_t Parcel::writeNullReference(size_t * handle) {
-    LOG_BUFFER("writeNullReference -> %zu", mObjectsSize);
-    status_t status = incrementNumReferences();
-    if (status != OK)
-        return status;
-
-    binder_buffer_object obj {
-        .hdr = { .type = BINDER_TYPE_PTR },
-        .flags = BINDER_BUFFER_FLAG_REF,
-    };
-
-    if (handle != nullptr)
-        // We use an index into mObjects as a handle
-        *handle = mObjectsSize;
-    return writeObject(obj);
-}
-
-status_t Parcel::writeEmbeddedNullReference(size_t * handle,
-        size_t parent_buffer_handle, size_t parent_offset) {
-    LOG_BUFFER("writeEmbeddedNullReference(parent = (%zu, %zu)) -> %zu",
-        parent_buffer_handle,
-        parent_offset,
-        mObjectsSize);
-    status_t status = incrementNumReferences();
-    if (status != OK)
-        return status;
-    if(!validateBufferParent(parent_buffer_handle, parent_offset))
-        return BAD_VALUE;
-    binder_buffer_object obj {
-        .hdr = { .type = BINDER_TYPE_PTR, },
-        .flags = BINDER_BUFFER_FLAG_REF | BINDER_BUFFER_FLAG_HAS_PARENT,
-        .parent = parent_buffer_handle,
-        .parent_offset = parent_offset,
-    };
-    if (handle != nullptr) {
-        // We use an index into mObjects as a handle
-        *handle = mObjectsSize;
-    }
-    return writeObject(obj);
-}
-
 void Parcel::clearCache() const {
     LOG_BUFFER("clearing cache.");
     mBufCachePos = 0;
@@ -994,7 +865,7 @@
         binder_size_t dataPos = mObjects[i];
         binder_buffer_object *obj =
             reinterpret_cast<binder_buffer_object*>(mData+dataPos);
-        if(!isBuffer(*obj))
+        if(obj->hdr.type != BINDER_TYPE_PTR)
             continue;
         BufferInfo ifo;
         ifo.index = i;
@@ -1132,7 +1003,7 @@
     if (len > INT32_MAX) {
         // don't accept size_t values which may have come from an
         // inadvertent conversion from a negative int.
-        return NULL;
+        return nullptr;
     }
 
     if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
@@ -1142,7 +1013,7 @@
         ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
         return data;
     }
-    return NULL;
+    return nullptr;
 }
 
 template<class T>
@@ -1344,7 +1215,7 @@
             return str;
         }
     }
-    return NULL;
+    return nullptr;
 }
 String16 Parcel::readString16() const
 {
@@ -1398,12 +1269,12 @@
     if (size >= 0 && size < INT32_MAX) {
         *outLen = size;
         const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));
-        if (str != NULL) {
+        if (str != nullptr) {
             return str;
         }
     }
     *outLen = 0;
-    return NULL;
+    return nullptr;
 }
 status_t Parcel::readStrongBinder(sp<IBinder>* val) const
 {
@@ -1528,7 +1399,7 @@
         ALOGW("Attempt to read object from Parcel %p at offset %zu that is not in the object list",
              this, DPOS);
     }
-    return NULL;
+    return nullptr;
 }
 
 template const flat_binder_object* Parcel::readObject<flat_binder_object>(size_t *objects_offset) const;
@@ -1575,7 +1446,7 @@
 
     const binder_buffer_object* buffer_obj = readObject<binder_buffer_object>(buffer_handle);
 
-    if (buffer_obj == nullptr || !isBuffer(*buffer_obj)) {
+    if (buffer_obj == nullptr || buffer_obj->hdr.type != BINDER_TYPE_PTR) {
         return BAD_VALUE;
     }
 
@@ -1633,48 +1504,6 @@
                       parent_buffer_handle, parent_offset, buffer_out);
 }
 
-// isRef if corresponds to a writeReference call, else corresponds to a writeBuffer call.
-// see ::android::hardware::writeReferenceToParcel for details.
-status_t Parcel::readReference(void const* *bufptr,
-                               size_t *buffer_handle, bool *isRef) const
-{
-    LOG_BUFFER("readReference");
-    const binder_buffer_object* buffer_obj = readObject<binder_buffer_object>();
-    LOG_BUFFER("    readReference: buf = %p, len = %zu, flags = %x",
-        (void*)buffer_obj->buffer, (size_t)buffer_obj->length,
-        (int)buffer_obj->flags);
-    // TODO need verification here
-    if (buffer_obj && buffer_obj->hdr.type == BINDER_TYPE_PTR) {
-        if (buffer_handle != nullptr) {
-            *buffer_handle = 0; // TODO fix this, as readBuffer would do
-        }
-        if(isRef != nullptr) {
-            *isRef = (buffer_obj->flags & BINDER_BUFFER_FLAG_REF) != 0;
-            LOG_BUFFER("    readReference: isRef = %d", *isRef);
-        }
-        // in read side, always use .buffer and .length.
-        if(bufptr != nullptr) {
-            *bufptr = (void*)buffer_obj->buffer;
-        }
-        return OK;
-    }
-
-    return BAD_VALUE;
-}
-
-// isRef if corresponds to a writeEmbeddedReference call, else corresponds to a writeEmbeddedBuffer call.
-// see ::android::hardware::writeEmbeddedReferenceToParcel for details.
-status_t Parcel::readEmbeddedReference(void const* *bufptr,
-                                       size_t *buffer_handle,
-                                       size_t /* parent_buffer_handle */,
-                                       size_t /* parent_offset */,
-                                       bool *isRef) const
-{
-    // TODO verify parent and offset
-    LOG_BUFFER("readEmbeddedReference");
-    return (readReference(bufptr, buffer_handle, isRef));
-}
-
 status_t Parcel::readEmbeddedNativeHandle(size_t parent_buffer_handle,
                                           size_t parent_offset,
                                           const native_handle_t **handle) const
@@ -1831,7 +1660,7 @@
         i--;
         const binder_buffer_object* buffer
             = reinterpret_cast<binder_buffer_object*>(mData+mObjects[i]);
-        if (isBuffer(*buffer)) {
+        if (buffer->hdr.type == BINDER_TYPE_PTR) {
             /* The binder kernel driver requires each buffer to be 8-byte
              * aligned */
             size_t alignedSize = (buffer->length + (BUFFER_ALIGNMENT_BYTES - 1))
@@ -1861,7 +1690,6 @@
     mObjectsSize = mObjectsCapacity = objectsCount;
     mNextObjectHint = 0;
     clearCache();
-    mNumRef = 0;
     mOwner = relFunc;
     mOwnerCookie = relCookie;
     for (size_t i = 0; i < mObjectsSize; i++) {
@@ -1895,14 +1723,10 @@
             if (flat->hdr.type == BINDER_TYPE_PTR) {
                 const binder_buffer_object* buffer
                     = reinterpret_cast<const binder_buffer_object*>(DATA+OBJS[i]);
-                if(isBuffer(*buffer)) {
-                    HexDump bufferDump((const uint8_t*)buffer->buffer, (size_t)buffer->length);
-                    bufferDump.setSingleLineCutoff(0);
-                    to << endl << "Object #" << i << " @ " << (void*)OBJS[i] << " (buffer size " << buffer->length << "):";
-                    to << indent << bufferDump << dedent;
-                } else {
-                    to << endl << "Object #" << i << " @ " << (void*)OBJS[i];
-                }
+                HexDump bufferDump((const uint8_t*)buffer->buffer, (size_t)buffer->length);
+                bufferDump.setSingleLineCutoff(0);
+                to << endl << "Object #" << i << " @ " << (void*)OBJS[i] << " (buffer size " << buffer->length << "):";
+                to << indent << bufferDump << dedent;
             } else {
                 to << endl << "Object #" << i << " @ " << (void*)OBJS[i] << ": "
                     << TypeCode(flat->hdr.type & 0x7f7f7f00)
@@ -2030,12 +1854,11 @@
     ALOGV("restartWrite Setting data pos of %p to %zu", this, mDataPos);
 
     free(mObjects);
-    mObjects = NULL;
+    mObjects = nullptr;
     mObjectsSize = mObjectsCapacity = 0;
     mNextObjectHint = 0;
     mHasFds = false;
     clearCache();
-    mNumRef = 0;
     mFdsKnown = true;
     mAllowFds = true;
 
@@ -2079,7 +1902,7 @@
             mError = NO_MEMORY;
             return NO_MEMORY;
         }
-        binder_size_t* objects = NULL;
+        binder_size_t* objects = nullptr;
 
         if (objectsSize) {
             objects = (binder_size_t*)calloc(objectsSize, sizeof(binder_size_t));
@@ -2106,7 +1929,7 @@
         }
         //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
         mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);
-        mOwner = NULL;
+        mOwner = nullptr;
 
         LOG_ALLOC("Parcel %p: taking ownership of %zu capacity", this, desired);
         pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
@@ -2182,7 +2005,7 @@
             return NO_MEMORY;
         }
 
-        if(!(mDataCapacity == 0 && mObjects == NULL
+        if(!(mDataCapacity == 0 && mObjects == nullptr
              && mObjectsCapacity == 0)) {
             ALOGE("continueWrite: %zu/%p/%zu/%zu", mDataCapacity, mObjects, mObjectsCapacity, desired);
         }
@@ -2207,22 +2030,21 @@
 {
     LOG_ALLOC("Parcel %p: initState", this);
     mError = NO_ERROR;
-    mData = 0;
+    mData = nullptr;
     mDataSize = 0;
     mDataCapacity = 0;
     mDataPos = 0;
     ALOGV("initState Setting data size of %p to %zu", this, mDataSize);
     ALOGV("initState Setting data pos of %p to %zu", this, mDataPos);
-    mObjects = NULL;
+    mObjects = nullptr;
     mObjectsSize = 0;
     mObjectsCapacity = 0;
     mNextObjectHint = 0;
     mHasFds = false;
     mFdsKnown = true;
     mAllowFds = true;
-    mOwner = NULL;
+    mOwner = nullptr;
     clearCache();
-    mNumRef = 0;
 
     // racing multiple init leads only to multiple identical write
     if (gMaxFds == 0) {
diff --git a/ProcessState.cpp b/ProcessState.cpp
index 37e3611..e652a44 100644
--- a/ProcessState.cpp
+++ b/ProcessState.cpp
@@ -68,7 +68,7 @@
 sp<ProcessState> ProcessState::self()
 {
     Mutex::Autolock _l(gProcessMutex);
-    if (gProcess != NULL) {
+    if (gProcess != nullptr) {
         return gProcess;
     }
     gProcess = new ProcessState(DEFAULT_BINDER_VM_SIZE);
@@ -82,7 +82,7 @@
 
 sp<ProcessState> ProcessState::initWithMmapSize(size_t mmap_size) {
     Mutex::Autolock _l(gProcessMutex);
-    if (gProcess != NULL) {
+    if (gProcess != nullptr) {
         LOG_ALWAYS_FATAL_IF(mmap_size != gProcess->getMmapSize(),
                 "ProcessState already initialized with a different mmap size.");
         return gProcess;
@@ -112,18 +112,18 @@
 {
     mLock.lock();
     sp<IBinder> object(
-        mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : NULL);
+        mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : nullptr);
     mLock.unlock();
 
     //printf("Getting context object %s for %p\n", String8(name).string(), caller.get());
 
-    if (object != NULL) return object;
+    if (object != nullptr) return object;
 
     // Don't attempt to retrieve contexts if we manage them
     if (mManagesContexts) {
         ALOGE("getContextObject(%s) failed, but we manage the contexts!\n",
             String8(name).string());
-        return NULL;
+        return nullptr;
     }
 
     IPCThreadState* ipc = IPCThreadState::self();
@@ -140,7 +140,7 @@
 
     ipc->flushCommands();
 
-    if (object != NULL) setContextObject(object, name);
+    if (object != nullptr) setContextObject(object, name);
     return object;
 }
 
@@ -184,8 +184,8 @@
         if (result == 0) {
             mManagesContexts = true;
         } else if (result == -1) {
-            mBinderContextCheckFunc = NULL;
-            mBinderContextUserData = NULL;
+            mBinderContextCheckFunc = nullptr;
+            mBinderContextUserData = nullptr;
             ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
         }
     }
@@ -201,7 +201,7 @@
 ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf) {
     binder_node_debug_info info = {};
 
-    uintptr_t* end = buf ? buf + buf_count : NULL;
+    uintptr_t* end = buf ? buf + buf_count : nullptr;
     size_t count = 0;
 
     do {
@@ -220,19 +220,49 @@
     return count;
 }
 
+// Queries the driver for the current strong reference count of the node
+// that the handle points to. Can only be used by the servicemanager.
+//
+// Returns -1 in case of failure, otherwise the strong reference count.
+ssize_t ProcessState::getStrongRefCountForNodeByHandle(int32_t handle) {
+    binder_node_info_for_ref info;
+    memset(&info, 0, sizeof(binder_node_info_for_ref));
+
+    info.handle = handle;
+
+    status_t result = ioctl(mDriverFD, BINDER_GET_NODE_INFO_FOR_REF, &info);
+
+    if (result != OK) {
+        static bool logged = false;
+        if (!logged) {
+          ALOGW("Kernel does not support BINDER_GET_NODE_INFO_FOR_REF.");
+          logged = true;
+        }
+        return -1;
+    }
+
+    return info.strong_count;
+}
+
 size_t ProcessState::getMmapSize() {
     return mMmapSize;
 }
 
+void ProcessState::setCallRestriction(CallRestriction restriction) {
+    LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull(), "Call restrictions must be set before the threadpool is started.");
+
+    mCallRestriction = restriction;
+}
+
 ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
 {
     const size_t N=mHandleToObject.size();
     if (N <= (size_t)handle) {
         handle_entry e;
-        e.binder = NULL;
-        e.refs = NULL;
+        e.binder = nullptr;
+        e.refs = nullptr;
         status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
-        if (err < NO_ERROR) return NULL;
+        if (err < NO_ERROR) return nullptr;
     }
     return &mHandleToObject.editItemAt(handle);
 }
@@ -245,12 +275,12 @@
 
     handle_entry* e = lookupHandleLocked(handle);
 
-    if (e != NULL) {
+    if (e != nullptr) {
         // We need to create a new BpHwBinder if there isn't currently one, OR we
         // are unable to acquire a weak reference on this current one.  See comment
         // in getWeakProxyForHandle() for more info about this.
         IBinder* b = e->binder;
-        if (b == NULL || !e->refs->attemptIncWeak(this)) {
+        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
             b = new BpHwBinder(handle);
             e->binder = b;
             if (b) e->refs = b->getWeakRefs();
@@ -275,7 +305,7 @@
 
     handle_entry* e = lookupHandleLocked(handle);
 
-    if (e != NULL) {
+    if (e != nullptr) {
         // We need to create a new BpHwBinder if there isn't currently one, OR we
         // are unable to acquire a weak reference on this current one.  The
         // attemptIncWeak() is safe because we know the BpHwBinder destructor will always
@@ -284,7 +314,7 @@
         // releasing a reference on this BpHwBinder, and a new reference on its handle
         // arriving from the driver.
         IBinder* b = e->binder;
-        if (b == NULL || !e->refs->attemptIncWeak(this)) {
+        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
             b = new BpHwBinder(handle);
             result = b;
             e->binder = b;
@@ -307,7 +337,7 @@
     // This handle may have already been replaced with a new BpHwBinder
     // (if someone failed the AttemptIncWeak() above); we don't want
     // to overwrite it.
-    if (e && e->binder == binder) e->binder = NULL;
+    if (e && e->binder == binder) e->binder = nullptr;
 }
 
 String8 ProcessState::makeBinderThreadName() {
@@ -329,24 +359,37 @@
 }
 
 status_t ProcessState::setThreadPoolConfiguration(size_t maxThreads, bool callerJoinsPool) {
-    LOG_ALWAYS_FATAL_IF(maxThreads < 1, "Binder threadpool must have a minimum of one thread.");
-    status_t result = NO_ERROR;
+    // if the caller joins the pool, then there will be one thread which is impossible.
+    LOG_ALWAYS_FATAL_IF(maxThreads == 0 && callerJoinsPool,
+           "Binder threadpool must have a minimum of one thread if caller joins pool.");
+
+    size_t threadsToAllocate = maxThreads;
+
+    // If the caller is going to join the pool it will contribute one thread to the threadpool.
+    // This is part of the API's contract.
+    if (callerJoinsPool) threadsToAllocate--;
+
+    // If we can, spawn one thread from userspace when the threadpool is started. This ensures
+    // that there is always a thread available to start more threads as soon as the threadpool
+    // is started.
+    bool spawnThreadOnStart = threadsToAllocate > 0;
+    if (spawnThreadOnStart) threadsToAllocate--;
+
     // the BINDER_SET_MAX_THREADS ioctl really tells the kernel how many threads
     // it's allowed to spawn, *in addition* to any threads we may have already
-    // spawned locally. If 'callerJoinsPool' is true, it means that the caller
-    // will join the threadpool, and so the kernel needs to create one less thread.
-    // If 'callerJoinsPool' is false, we will still spawn a thread locally, and we should
-    // also tell the kernel to create one less thread than what was requested here.
-    size_t kernelMaxThreads = maxThreads - 1;
-    if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &kernelMaxThreads) != -1) {
-        AutoMutex _l(mLock);
-        mMaxThreads = maxThreads;
-        mSpawnThreadOnStart = !callerJoinsPool;
-    } else {
-        result = -errno;
-        ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
+    // spawned locally.
+    size_t kernelMaxThreads = threadsToAllocate;
+
+    AutoMutex _l(mLock);
+    if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &kernelMaxThreads) == -1) {
+        ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
+        return -errno;
     }
-    return result;
+
+    mMaxThreads = maxThreads;
+    mSpawnThreadOnStart = spawnThreadOnStart;
+
+    return NO_ERROR;
 }
 
 size_t ProcessState::getMaxThreads() {
@@ -393,19 +436,20 @@
     , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
     , mStarvationStartTimeMs(0)
     , mManagesContexts(false)
-    , mBinderContextCheckFunc(NULL)
-    , mBinderContextUserData(NULL)
+    , mBinderContextCheckFunc(nullptr)
+    , mBinderContextUserData(nullptr)
     , mThreadPoolStarted(false)
     , mSpawnThreadOnStart(true)
     , mThreadPoolSeq(1)
     , mMmapSize(mmap_size)
+    , mCallRestriction(CallRestriction::NONE)
 {
     if (mDriverFD >= 0) {
         // mmap the binder, providing a chunk of virtual address space to receive transactions.
-        mVMStart = mmap(0, mMmapSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
+        mVMStart = mmap(nullptr, 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");
+            ALOGE("Mmapping /dev/hwbinder failed: %s\n", strerror(errno));
             close(mDriverFD);
             mDriverFD = -1;
         }
diff --git a/Static.cpp b/Static.cpp
index a84f811..87f632c 100644
--- a/Static.cpp
+++ b/Static.cpp
@@ -76,20 +76,5 @@
 Mutex& gProcessMutex = *new Mutex;
 sp<ProcessState> gProcess;
 
-class LibHwbinderIPCtStatics
-{
-public:
-    LibHwbinderIPCtStatics()
-    {
-    }
-    
-    ~LibHwbinderIPCtStatics()
-    {
-        IPCThreadState::shutdown();
-    }
-};
-
-static LibHwbinderIPCtStatics gIPCStatics;
-
 }   // namespace hardware
 }   // namespace android
diff --git a/include/hwbinder/Binder.h b/include/hwbinder/Binder.h
index 1efa342..960ea80 100644
--- a/include/hwbinder/Binder.h
+++ b/include/hwbinder/Binder.h
@@ -37,13 +37,13 @@
                                     TransactCallback callback = nullptr);
 
     virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
-                                    void* cookie = NULL,
+                                    void* cookie = nullptr,
                                     uint32_t flags = 0);
 
     virtual status_t    unlinkToDeath(  const wp<DeathRecipient>& recipient,
-                                        void* cookie = NULL,
+                                        void* cookie = nullptr,
                                         uint32_t flags = 0,
-                                        wp<DeathRecipient>* outRecipient = NULL);
+                                        wp<DeathRecipient>* outRecipient = nullptr);
 
     virtual void        attachObject(   const void* objectID,
                                         void* object,
@@ -91,12 +91,13 @@
 class BpHwRefBase : public virtual RefBase
 {
 protected:
-                            BpHwRefBase(const sp<IBinder>& o);
+    explicit                BpHwRefBase(const sp<IBinder>& o);
     virtual                 ~BpHwRefBase();
     virtual void            onFirstRef();
     virtual void            onLastStrongRef(const void* id);
     virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
 
+public:
     inline  IBinder*        remote() const          { return mRemote; }
 
 private:
diff --git a/include/hwbinder/BpHwBinder.h b/include/hwbinder/BpHwBinder.h
index dc3073a..9f86a94 100644
--- a/include/hwbinder/BpHwBinder.h
+++ b/include/hwbinder/BpHwBinder.h
@@ -39,12 +39,12 @@
                                     TransactCallback callback = nullptr);
 
     virtual status_t    linkToDeath(const sp<DeathRecipient>& recipient,
-                                    void* cookie = NULL,
+                                    void* cookie = nullptr,
                                     uint32_t flags = 0);
     virtual status_t    unlinkToDeath(  const wp<DeathRecipient>& recipient,
-                                        void* cookie = NULL,
+                                        void* cookie = nullptr,
                                         uint32_t flags = 0,
-                                        wp<DeathRecipient>* outRecipient = NULL);
+                                        wp<DeathRecipient>* outRecipient = nullptr);
 
     virtual void        attachObject(   const void* objectID,
                                         void* object,
@@ -55,9 +55,13 @@
 
     virtual BpHwBinder*   remoteBinder();
 
-            status_t    setConstantData(const void* data, size_t size);
             void        sendObituary();
-
+                        // This refcount includes:
+                        // 1. Strong references to the node by this and other processes
+                        // 2. Temporary strong references held by the kernel during a
+                        //    transaction on the node.
+                        // It does NOT include local strong references to the node
+            ssize_t     getNodeStrongRefCount();
     class ObjectManager
     {
     public:
diff --git a/include/hwbinder/BufferedTextOutput.h b/include/hwbinder/BufferedTextOutput.h
index 73ba6e0..401331a 100644
--- a/include/hwbinder/BufferedTextOutput.h
+++ b/include/hwbinder/BufferedTextOutput.h
@@ -33,7 +33,7 @@
         MULTITHREADED = 0x0001
     };
     
-                        BufferedTextOutput(uint32_t flags = 0);
+    explicit            BufferedTextOutput(uint32_t flags = 0);
     virtual             ~BufferedTextOutput();
     
     virtual status_t    print(const char* txt, size_t len);
diff --git a/include/hwbinder/Debug.h b/include/hwbinder/Debug.h
index 03127cb..0c173a4 100644
--- a/include/hwbinder/Debug.h
+++ b/include/hwbinder/Debug.h
@@ -32,12 +32,12 @@
 typedef void (*debugPrintFunc)(void* cookie, const char* txt);
 
 void printTypeCode(uint32_t typeCode,
-    debugPrintFunc func = 0, void* cookie = 0);
+    debugPrintFunc func = nullptr, void* cookie = nullptr);
 
 void printHexData(int32_t indent, const void *buf, size_t length,
     size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
     size_t alignment=0, bool cArrayStyle=false,
-    debugPrintFunc func = 0, void* cookie = 0);
+    debugPrintFunc func = nullptr, void* cookie = nullptr);
 
 ssize_t getHWBinderKernelReferences(size_t count, uintptr_t* buf);
 
diff --git a/include/hwbinder/IBinder.h b/include/hwbinder/IBinder.h
index 5648101..b8f3b0e 100644
--- a/include/hwbinder/IBinder.h
+++ b/include/hwbinder/IBinder.h
@@ -86,7 +86,7 @@
      * directly do with it now that it has passed on.)
      */
     virtual status_t        linkToDeath(const sp<DeathRecipient>& recipient,
-                                        void* cookie = NULL,
+                                        void* cookie = nullptr,
                                         uint32_t flags = 0) = 0;
 
     /**
@@ -97,19 +97,39 @@
      * added with that cookie will be unlinked.
      */
     virtual status_t        unlinkToDeath(  const wp<DeathRecipient>& recipient,
-                                            void* cookie = NULL,
+                                            void* cookie = nullptr,
                                             uint32_t flags = 0,
-                                            wp<DeathRecipient>* outRecipient = NULL) = 0;
+                                            wp<DeathRecipient>* outRecipient = nullptr) = 0;
 
     virtual bool            checkSubclass(const void* subclassID) const;
 
     typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
 
+    /**
+     * This object is attached for the lifetime of this binder object. When
+     * this binder object is destructed, the cleanup function of all attached
+     * objects are invoked with their respective objectID, object, and
+     * cleanupCookie. Access to these APIs can be made from multiple threads,
+     * but calls from different threads are allowed to be interleaved.
+     */
     virtual void            attachObject(   const void* objectID,
                                             void* object,
                                             void* cleanupCookie,
                                             object_cleanup_func func) = 0;
+    /**
+     * Returns object attached with attachObject.
+     */
     virtual void*           findObject(const void* objectID) const = 0;
+    /**
+     * WARNING: this API does not call the cleanup function for legacy reasons.
+     * It also does not return void* for legacy reasons. If you need to detach
+     * an object and destroy it, there are two options:
+     * - if you can, don't call detachObject and instead wait for the destructor
+     *   to clean it up.
+     * - manually retrieve and destruct the object (if multiple of your threads
+     *   are accessing these APIs, you must guarantee that attachObject isn't
+     *   called after findObject and before detachObject is called).
+     */
     virtual void            detachObject(const void* objectID) = 0;
 
     virtual BHwBinder*        localBinder();
diff --git a/include/hwbinder/IInterface.h b/include/hwbinder/IInterface.h
index 17cbae9..96189ab 100644
--- a/include/hwbinder/IInterface.h
+++ b/include/hwbinder/IInterface.h
@@ -41,7 +41,7 @@
 class BpInterface : public INTERFACE, public IInterface, public BpHwRefBase
 {
 public:
-                                BpInterface(const sp<IBinder>& remote);
+    explicit                    BpInterface(const sp<IBinder>& remote);
     virtual IBinder*            onAsBinder();
 };
 
diff --git a/include/hwbinder/IPCThreadState.h b/include/hwbinder/IPCThreadState.h
index 32eea8c..b6e1089 100644
--- a/include/hwbinder/IPCThreadState.h
+++ b/include/hwbinder/IPCThreadState.h
@@ -22,12 +22,17 @@
 #include <hwbinder/ProcessState.h>
 #include <utils/Vector.h>
 
+#include <functional>
+
 #if defined(_WIN32)
 typedef  int  uid_t;
 #endif
 
 // ---------------------------------------------------------------------------
 namespace android {
+
+class IPCThreadStateBase;
+
 namespace hardware {
 
 class IPCThreadState
@@ -84,13 +89,6 @@
 
     static  void                shutdown();
 
-    // Call this to disable switching threads to background scheduling when
-    // receiving incoming IPC calls.  This is specifically here for the
-    // Android system process, since it expects to have background apps calling
-    // in to it but doesn't want to acquire locks in its services while in
-    // the background.
-    static  void                disableBackgroundScheduling(bool disable);
-
             // Call blocks until the number of executing binder threads is less than
             // the maximum number of binder threads threads allowed for this process.
             void                blockUntilThreadAvailable();
@@ -101,13 +99,43 @@
             bool                isLooperThread();
             bool                isOnlyBinderThread();
 
-private:
-                                IPCThreadState();
-                                ~IPCThreadState();
+            // Is this thread currently serving a hwbinder call. This method
+            // returns true if while traversing backwards from the function call
+            // stack for this thread, we encounter a function serving a hwbinder
+            // call before encountering a binder call / hitting the end of the
+            // call stack.
+            // Eg: If thread T1 went through the following call pattern
+            //     1) T1 receives and executes binder call B1.
+            //     2) While handling B1, T1 makes hwbinder call H1.
+            //     3) The handler of H1, calls into T1 with a callback H2.
+            // If isServingCall() is called during B1 before 3), this method
+            // will return false, else true.
+            //
+            //  ----
+            // | H2 | ---> While callback H2 is being handled during 3).
+            //  ----
+            // | B1 | ---> While B1 is being handled, hwbinder call H1 made.
+            //  ----
+            // Fig: Thread Call stack while handling H2.
+            //
+            // This is since after 3), while traversing the thread call stack,
+            // we hit a hwbinder call before a binder call / end of stack.
+            // This method may be typically used to determine whether to use
+            // hardware::IPCThreadState methods or IPCThreadState methods to
+            // infer information about thread state.
+            bool isServingCall() const;
+
+            // Tasks which are done on the binder thread after the thread returns to the
+            // threadpool.
+            void addPostCommandTask(const std::function<void(void)>& task);
+
+           private:
+            IPCThreadState();
+            ~IPCThreadState();
 
             status_t            sendReply(const Parcel& reply, uint32_t flags);
             status_t            waitForResponse(Parcel *reply,
-                                                status_t *acquireResult=NULL);
+                                                status_t *acquireResult=nullptr);
             status_t            talkWithDriver(bool doReceive=true);
             status_t            writeTransactionData(int32_t cmd,
                                                      uint32_t binderFlags,
@@ -129,7 +157,6 @@
                                            void* cookie);
 
     const   sp<ProcessState>    mProcess;
-    const   pid_t               mMyThreadId;
             Vector<BHwBinder*>    mPendingStrongDerefs;
             Vector<RefBase::weakref_type*> mPendingWeakDerefs;
             Vector<RefBase*>    mPostWriteStrongDerefs;
@@ -142,9 +169,13 @@
             uid_t               mCallingUid;
             int32_t             mStrictModePolicy;
             int32_t             mLastTransactionBinderFlags;
-            sp<BHwBinder>         mContextObject;
             bool                mIsLooper;
             bool mIsPollingThread;
+
+            std::vector<std::function<void(void)>> mPostCommandTasks;
+            IPCThreadStateBase *mIPCThreadStateBase;
+
+            ProcessState::CallRestriction mCallRestriction;
 };
 
 }; // namespace hardware
diff --git a/include/hwbinder/Parcel.h b/include/hwbinder/Parcel.h
index f6e45d5..99d0719 100644
--- a/include/hwbinder/Parcel.h
+++ b/include/hwbinder/Parcel.h
@@ -65,7 +65,6 @@
     // Parses the RPC header, returning true if the interface name
     // in the header matches the expected interface from the caller.
     bool                enforceInterface(const char* interface) const;
-    bool                checkInterface(IBinder*) const;
 
     void                freeData();
 
@@ -106,16 +105,6 @@
     status_t            writeEmbeddedBuffer(const void *buffer, size_t length, size_t *handle,
                             size_t parent_buffer_handle, size_t parent_offset);
 public:
-    status_t            writeReference(size_t *handle,
-                                       size_t child_buffer_handle, size_t child_offset);
-    status_t            writeEmbeddedReference(size_t *handle,
-                                               size_t child_buffer_handle, size_t child_offset,
-                                               size_t parent_buffer_handle, size_t parent_offset);
-    status_t            writeNullReference(size_t *handle);
-    status_t            writeEmbeddedNullReference(size_t *handle,
-                                                   size_t parent_buffer_handle, size_t parent_offset);
-
-
     status_t            writeEmbeddedNativeHandle(const native_handle_t *handle,
                             size_t parent_buffer_handle, size_t parent_offset);
     status_t            writeNativeHandleNoDup(const native_handle* handle, bool embedded,
@@ -172,11 +161,6 @@
                                                    size_t parent_offset,
                                                    const void **buffer_out) const;
 
-    status_t            readReference(void const* *bufptr,
-                                      size_t *buffer_handle, bool *isRef) const;
-    status_t            readEmbeddedReference(void const* *bufptr, size_t *buffer_handle,
-                                              size_t parent_buffer_handle, size_t parent_offset,
-                                              bool *isRef) const;
     status_t            readEmbeddedNativeHandle(size_t parent_buffer_handle,
                            size_t parent_offset, const native_handle_t **handle) const;
     status_t            readNullableEmbeddedNativeHandle(size_t parent_buffer_handle,
@@ -241,7 +225,6 @@
                                        ) const;
 
 private:
-    status_t            incrementNumReferences();
     bool                validateBufferChild(size_t child_buffer_handle,
                                             size_t child_offset) const;
     bool                validateBufferParent(size_t parent_buffer_handle,
@@ -299,7 +282,8 @@
     size_t              mObjectsSize;
     size_t              mObjectsCapacity;
     mutable size_t      mNextObjectHint;
-    size_t              mNumRef;
+
+    [[deprecated]] size_t mNumRef;
 
     mutable bool        mFdsKnown;
     mutable bool        mHasFds;
diff --git a/include/hwbinder/ProcessState.h b/include/hwbinder/ProcessState.h
index 2f72059..6490a8d 100644
--- a/include/hwbinder/ProcessState.h
+++ b/include/hwbinder/ProcessState.h
@@ -70,11 +70,29 @@
             void                giveThreadPoolName();
 
             ssize_t             getKernelReferences(size_t count, uintptr_t* buf);
+                                // This refcount includes:
+                                // 1. Strong references to the node by this  and other processes
+                                // 2. Temporary strong references held by the kernel during a
+                                //    transaction on the node.
+                                // It does NOT include local strong references to the node
+            ssize_t             getStrongRefCountForNodeByHandle(int32_t handle);
             size_t              getMmapSize();
+
+            enum class CallRestriction {
+                // all calls okay
+                NONE,
+                // log when calls are blocking
+                ERROR_IF_NOT_ONEWAY,
+                // abort process on blocking calls
+                FATAL_IF_NOT_ONEWAY,
+            };
+            // Sets calling restrictions for all transactions in this process. This must be called
+            // before any threads are spawned.
+            void setCallRestriction(CallRestriction restriction);
+
 private:
     friend class IPCThreadState;
-
-                                ProcessState(size_t mmap_size);
+            explicit            ProcessState(size_t mmap_size);
                                 ~ProcessState();
 
                                 ProcessState(const ProcessState& o);
@@ -117,7 +135,9 @@
             bool                mThreadPoolStarted;
             bool                mSpawnThreadOnStart;
     volatile int32_t            mThreadPoolSeq;
-            size_t              mMmapSize;
+            const size_t        mMmapSize;
+
+            CallRestriction     mCallRestriction;
 };
 
 }; // namespace hardware
diff --git a/include/hwbinder/TextOutput.h b/include/hwbinder/TextOutput.h
index d92c442..cdc60e9 100644
--- a/include/hwbinder/TextOutput.h
+++ b/include/hwbinder/TextOutput.h
@@ -39,7 +39,7 @@
     
     class Bundle {
     public:
-        inline Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
+        inline explicit Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
         inline ~Bundle() { mTO.popBundle(); }
     private:
         TextOutput&     mTO;
@@ -81,7 +81,7 @@
 class TypeCode
 {
 public:
-    inline TypeCode(uint32_t code);
+    inline explicit TypeCode(uint32_t code);
     inline ~TypeCode();
 
     inline uint32_t typeCode() const;
diff --git a/include/hwbinder/binder_kernel.h b/include/hwbinder/binder_kernel.h
index 27a0595..9d9ed70 100644
--- a/include/hwbinder/binder_kernel.h
+++ b/include/hwbinder/binder_kernel.h
@@ -27,26 +27,10 @@
  */
 
 enum {
-	BINDER_BUFFER_FLAG_REF          = 1U << 1,
-};
-
-enum {
         FLAT_BINDER_FLAG_SCHEDPOLICY_MASK = 0x600,
         FLAT_BINDER_FLAG_SCHEDPOLICY_SHIFT = 9,
         FLAT_BINDER_FLAG_INHERIT_RT = 0x800,
-        FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
 };
 
-#define BINDER_SET_CONTEXT_MGR_EXT      _IOW('b', 13, struct flat_binder_object)
-
-struct binder_transaction_data_secctx {
-        struct binder_transaction_data transaction_data;
-        binder_uintptr_t secctx;
-};
-
-enum {
-        BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
-                              struct binder_transaction_data_secctx),
-};
 
 #endif // ANDROID_HARDWARE_BINDER_KERNEL_H
diff --git a/vts/performance/Android.bp b/vts/performance/Android.bp
index c5fa2a0..c6b74cf 100644
--- a/vts/performance/Android.bp
+++ b/vts/performance/Android.bp
@@ -29,14 +29,24 @@
         "libutils",
         "libcutils",
     ],
+
+    static_libs: ["android.hardware.tests.libhwbinder@1.0"],
+
+    // Allow dlsym'ing self for statically linked passthrough implementations
+    ldflags: ["-rdynamic"],
+
+    // impls should never be static, these are used only for testing purposes
+    // and test portability since this test pairs with specific hal
+    // implementations
+    whole_static_libs: [
+        "android.hardware.tests.libhwbinder@1.0-impl",
+    ],
 }
 
 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.
@@ -51,6 +61,8 @@
     shared_libs: [
         "libbinder",
         "libutils",
+    ],
+    static_libs: [
         "android.hardware.tests.libbinder",
     ],
 }
@@ -60,8 +72,6 @@
     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.
@@ -73,8 +83,4 @@
         "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/PerfTest.h b/vts/performance/PerfTest.h
index 3fa4b8d..2ca1d89 100644
--- a/vts/performance/PerfTest.h
+++ b/vts/performance/PerfTest.h
@@ -34,7 +34,7 @@
 class Pipe {
    public:
     static tuple<Pipe, Pipe> createPipePair();
-    Pipe(Pipe&& rval);
+    Pipe(Pipe&& rval) noexcept;
     ~Pipe();
     inline void signal() {
         bool val = true;