diff options
author | Jayant Chowdhary <jchowdhary@google.com> | 2018-10-02 20:14:37 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-10-02 20:14:37 +0000 |
commit | 05ada29dee6a5651fe0a8065ed143500735eccbc (patch) | |
tree | 0aaaf83d3653b785a609a740382f3ee97d33a792 | |
parent | c7691e696aab576843404290886ff70315592f6e (diff) | |
parent | dac6dc887580ad7b484223041388276f64ddf35f (diff) | |
download | native-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.bp | 1 | ||||
-rw-r--r-- | libs/binder/IPCThreadState.cpp | 10 | ||||
-rw-r--r-- | libs/binder/include/binder/IPCThreadState.h | 30 | ||||
-rw-r--r-- | libs/binderthreadstate/Android.bp | 44 | ||||
-rw-r--r-- | libs/binderthreadstate/IPCThreadStateBase.cpp | 89 | ||||
-rw-r--r-- | libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h | 44 |
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 |