Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 51fd1b17 authored by Jayant Chowdhary's avatar Jayant Chowdhary Committed by android-build-merger
Browse files

Merge "Reland "IPCThreadState: Add a public method to probe if a binder call...

Merge "Reland "IPCThreadState: Add a public method to probe if a binder call is being served.""" am: 05ada29d
am: 36cfafc6

Change-Id: If2843a096fdfa729fb9bb3d1b13fcbcc0c7fcea8
parents bbfbd090 36cfafc6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ cc_library_shared {
        "liblog",
        "libcutils",
        "libutils",
        "libbinderthreadstate",
    ],

    header_libs: [
+10 −0
Original line number Diff line number Diff line
@@ -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);
+30 −0
Original line number Diff line number Diff line
@@ -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
+44 −0
Original line number Diff line number Diff line
// 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",
    ],
}
+89 −0
Original line number Diff line number Diff line
/*
 * 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
Loading