Allow error/abort for non-oneway calls.

Low-level processes like init might not want to make blocking calls.
This provides the mechanism to programmatically enforce that.

Test: enable ERROR_BLOCKING on process and look at callstacks
Bug: 36424585

Change-Id: I6dad33271108768f8bfc4723bf3eeddbf9720395
diff --git a/IPCThreadState.cpp b/IPCThreadState.cpp
index c7c71be..9910d4f 100644
--- a/IPCThreadState.cpp
+++ b/IPCThreadState.cpp
@@ -25,6 +25,7 @@
 #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>
@@ -635,6 +636,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 but is restricted.");
+                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.");
+            }
+        }
+
         #if 0
         if (code == 4) { // relayout
             ALOGI(">>>>>> CALLING transaction 4");
@@ -757,7 +768,8 @@
       mStrictModePolicy(0),
       mLastTransactionBinderFlags(0),
       mIsLooper(false),
-      mIsPollingThread(false) {
+      mIsPollingThread(false),
+      mCallRestriction(mProcess->mCallRestriction) {
     pthread_setspecific(gTLS, this);
     clearCaller();
     mIn.setDataCapacity(256);
diff --git a/ProcessState.cpp b/ProcessState.cpp
index 84fb8f7..e9e63cb 100644
--- a/ProcessState.cpp
+++ b/ProcessState.cpp
@@ -231,6 +231,12 @@
     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();
@@ -419,6 +425,7 @@
     , 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.
diff --git a/include/hwbinder/IPCThreadState.h b/include/hwbinder/IPCThreadState.h
index f2112c0..65f458d 100644
--- a/include/hwbinder/IPCThreadState.h
+++ b/include/hwbinder/IPCThreadState.h
@@ -174,6 +174,8 @@
 
             std::vector<std::function<void(void)>> mPostCommandTasks;
             IPCThreadStateBase *mIPCThreadStateBase;
+
+            ProcessState::CallRestriction mCallRestriction;
 };
 
 }; // namespace hardware
diff --git a/include/hwbinder/ProcessState.h b/include/hwbinder/ProcessState.h
index f02b003..c42d8a8 100644
--- a/include/hwbinder/ProcessState.h
+++ b/include/hwbinder/ProcessState.h
@@ -77,6 +77,19 @@
                                 // 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;
 
@@ -124,6 +137,8 @@
             bool                mSpawnThreadOnStart;
     volatile int32_t            mThreadPoolSeq;
             const size_t        mMmapSize;
+
+            CallRestriction     mCallRestriction;
 };
 
 }; // namespace hardware