summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJayant Chowdhary <jchowdhary@google.com>2018-10-02 20:14:37 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-10-02 20:14:37 +0000
commit05ada29dee6a5651fe0a8065ed143500735eccbc (patch)
tree0aaaf83d3653b785a609a740382f3ee97d33a792
parentc7691e696aab576843404290886ff70315592f6e (diff)
parentdac6dc887580ad7b484223041388276f64ddf35f (diff)
downloadnative-05ada29dee6a5651fe0a8065ed143500735eccbc.tar.gz
Merge "Reland "IPCThreadState: Add a public method to probe if a binder call is being served."""
-rw-r--r--libs/binder/Android.bp1
-rw-r--r--libs/binder/IPCThreadState.cpp10
-rw-r--r--libs/binder/include/binder/IPCThreadState.h30
-rw-r--r--libs/binderthreadstate/Android.bp44
-rw-r--r--libs/binderthreadstate/IPCThreadStateBase.cpp89
-rw-r--r--libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h44
6 files changed, 218 insertions, 0 deletions
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 61b881861b..da10687476 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -119,6 +119,7 @@ cc_library_shared {
"liblog",
"libcutils",
"libutils",
+ "libbinderthreadstate",
],
header_libs: [
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index b2217b5333..f052bcb982 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "IPCThreadState"
#include <binder/IPCThreadState.h>
+#include <binderthreadstate/IPCThreadStateBase.h>
#include <binder/Binder.h>
#include <binder/BpBinder.h>
@@ -742,6 +743,7 @@ IPCThreadState::IPCThreadState()
clearCaller();
mIn.setDataCapacity(256);
mOut.setDataCapacity(256);
+ mIPCThreadStateBase = IPCThreadStateBase::self();
}
IPCThreadState::~IPCThreadState()
@@ -1082,6 +1084,9 @@ status_t IPCThreadState::executeCommand(int32_t cmd)
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;
+ //Record the fact that we're in a binder call.
+ mIPCThreadStateBase->pushCurrentState(
+ IPCThreadStateBase::CallState::BINDER);
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
@@ -1129,6 +1134,7 @@ status_t IPCThreadState::executeCommand(int32_t cmd)
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
+ mIPCThreadStateBase->popCurrentState();
//ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
// mCallingPid, origPid, origUid);
@@ -1192,6 +1198,10 @@ status_t IPCThreadState::executeCommand(int32_t cmd)
return result;
}
+bool IPCThreadState::isServingCall() const {
+ return mIPCThreadStateBase->getCurrentBinderCallState() == IPCThreadStateBase::CallState::BINDER;
+}
+
void IPCThreadState::threadDestructor(void *st)
{
IPCThreadState* const self = static_cast<IPCThreadState*>(st);
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index dce3f3856b..40b51adb06 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -29,6 +29,8 @@ typedef int uid_t;
// ---------------------------------------------------------------------------
namespace android {
+class IPCThreadStateBase;
+
class IPCThreadState
{
public:
@@ -89,6 +91,33 @@ public:
// the maximum number of binder threads threads allowed for this process.
void blockUntilThreadAvailable();
+
+ // Is this thread currently serving a binder call. This method
+ // returns true if while traversing backwards from the function call
+ // stack for this thread, we encounter a function serving a binder
+ // call before encountering a hwbinder call / hitting the end of the
+ // call stack.
+ // Eg: If thread T1 went through the following call pattern
+ // 1) T1 receives and executes hwbinder call H1.
+ // 2) While handling H1, T1 makes binder call B1.
+ // 3) The handler of B1, calls into T1 with a callback B2.
+ // If isServingCall() is called during H1 before 3), this method
+ // will return false, else true.
+ //
+ // ----
+ // | B2 | ---> While callback B2 is being handled, during 3).
+ // ----
+ // | H1 | ---> While H1 is being handled.
+ // ----
+ // Fig: Thread Call stack while handling B2
+ //
+ // This is since after 3), while traversing the thread call stack,
+ // we hit a binder call before a hwbinder 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;
+
private:
IPCThreadState();
~IPCThreadState();
@@ -128,6 +157,7 @@ private:
uid_t mCallingUid;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
+ IPCThreadStateBase *mIPCThreadStateBase;
};
}; // namespace android
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
new file mode 100644
index 0000000000..7106cbbf75
--- /dev/null
+++ b/libs/binderthreadstate/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2018 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_library {
+ name: "libbinderthreadstate",
+ recovery_available: true,
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ srcs: [
+ "IPCThreadStateBase.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libcutils",
+ "libutils",
+ ],
+
+ export_include_dirs: ["include"],
+
+ sanitize: {
+ misc_undefined: ["integer"],
+ },
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/libs/binderthreadstate/IPCThreadStateBase.cpp b/libs/binderthreadstate/IPCThreadStateBase.cpp
new file mode 100644
index 0000000000..fede151774
--- /dev/null
+++ b/libs/binderthreadstate/IPCThreadStateBase.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "IPCThreadStateBase"
+
+#include <binderthreadstate/IPCThreadStateBase.h>
+#include <android-base/macros.h>
+
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <pthread.h>
+
+namespace android {
+
+static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool gHaveTLS = false;
+static pthread_key_t gTLS = 0;
+
+IPCThreadStateBase::IPCThreadStateBase() {
+ pthread_setspecific(gTLS, this);
+}
+
+IPCThreadStateBase* IPCThreadStateBase::self()
+{
+ if (gHaveTLS) {
+restart:
+ const pthread_key_t k = gTLS;
+ IPCThreadStateBase* st = (IPCThreadStateBase*)pthread_getspecific(k);
+ if (st) return st;
+ return new IPCThreadStateBase;
+ }
+
+ pthread_mutex_lock(&gTLSMutex);
+ if (!gHaveTLS) {
+ int key_create_value = pthread_key_create(&gTLS, threadDestructor);
+ if (key_create_value != 0) {
+ pthread_mutex_unlock(&gTLSMutex);
+ ALOGW("IPCThreadStateBase::self() unable to create TLS key, expect a crash: %s\n",
+ strerror(key_create_value));
+ return nullptr;
+ }
+ gHaveTLS = true;
+ }
+ pthread_mutex_unlock(&gTLSMutex);
+ goto restart;
+}
+
+void IPCThreadStateBase::pushCurrentState(CallState callState) {
+ mCallStateStack.emplace(callState);
+}
+
+IPCThreadStateBase::CallState IPCThreadStateBase::popCurrentState() {
+ ALOG_ASSERT(mCallStateStack.size > 0);
+ CallState val = mCallStateStack.top();
+ mCallStateStack.pop();
+ return val;
+}
+
+IPCThreadStateBase::CallState IPCThreadStateBase::getCurrentBinderCallState() {
+ if (mCallStateStack.size() > 0) {
+ return mCallStateStack.top();
+ }
+ return CallState::NONE;
+}
+
+void IPCThreadStateBase::threadDestructor(void *st)
+{
+ IPCThreadStateBase* const self = static_cast<IPCThreadStateBase*>(st);
+ if (self) {
+ delete self;
+ }
+}
+
+}; // namespace android
diff --git a/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
new file mode 100644
index 0000000000..6fdcc84054
--- /dev/null
+++ b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
+#define BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
+
+#include <stack>
+namespace android {
+
+class IPCThreadStateBase {
+public:
+ enum CallState {
+ HWBINDER,
+ BINDER,
+ NONE,
+ };
+ static IPCThreadStateBase* self();
+ void pushCurrentState(CallState callState);
+ CallState popCurrentState();
+ CallState getCurrentBinderCallState();
+
+private:
+ IPCThreadStateBase();
+ static void threadDestructor(void *st);
+
+ std::stack<CallState> mCallStateStack;
+};
+
+}; // namespace android
+
+#endif // BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H