123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- /*
- * Copyright (C) 2005 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 "ProcessState"
- #include <cutils/process_name.h>
- #include <binder/ProcessState.h>
- #include <utils/Atomic.h>
- #include <binder/BpBinder.h>
- #include <binder/IPCThreadState.h>
- #include <utils/Log.h>
- #include <utils/String8.h>
- #include <binder/IServiceManager.h>
- #include <utils/String8.h>
- #include <utils/threads.h>
- #include <private/binder/binder_module.h>
- #include <private/binder/Static.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
- #define DEFAULT_MAX_BINDER_THREADS 15
- // ---------------------------------------------------------------------------
- namespace android {
- class PoolThread : public Thread
- {
- public:
- PoolThread(bool isMain)
- : mIsMain(isMain)
- {
- }
-
- protected:
- virtual bool threadLoop()
- {
- IPCThreadState::self()->joinThreadPool(mIsMain);
- return false;
- }
-
- const bool mIsMain;
- };
- sp<ProcessState> ProcessState::self()
- {
- Mutex::Autolock _l(gProcessMutex);
- if (gProcess != NULL) {
- return gProcess;
- }
- gProcess = new ProcessState;
- return gProcess;
- }
- void ProcessState::setContextObject(const sp<IBinder>& object)
- {
- setContextObject(object, String16("default"));
- }
- sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
- {
- return getStrongProxyForHandle(0);
- }
- void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name)
- {
- AutoMutex _l(mLock);
- mContexts.add(name, object);
- }
- sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinder>& caller)
- {
- mLock.lock();
- sp<IBinder> object(
- mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : NULL);
- mLock.unlock();
-
- //printf("Getting context object %s for %p\n", String8(name).string(), caller.get());
-
- if (object != NULL) 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;
- }
-
- IPCThreadState* ipc = IPCThreadState::self();
- {
- Parcel data, reply;
- // no interface token on this magic transaction
- data.writeString16(name);
- data.writeStrongBinder(caller);
- status_t result = ipc->transact(0 /*magic*/, 0, data, &reply, 0);
- if (result == NO_ERROR) {
- object = reply.readStrongBinder();
- }
- }
-
- ipc->flushCommands();
-
- if (object != NULL) setContextObject(object, name);
- return object;
- }
- void ProcessState::startThreadPool()
- {
- AutoMutex _l(mLock);
- if (!mThreadPoolStarted) {
- mThreadPoolStarted = true;
- spawnPooledThread(true);
- }
- }
- bool ProcessState::isContextManager(void) const
- {
- return mManagesContexts;
- }
- bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData)
- {
- if (!mManagesContexts) {
- AutoMutex _l(mLock);
- mBinderContextCheckFunc = checkFunc;
- mBinderContextUserData = userData;
- int dummy = 0;
- status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
- if (result == 0) {
- mManagesContexts = true;
- } else if (result == -1) {
- mBinderContextCheckFunc = NULL;
- mBinderContextUserData = NULL;
- ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
- }
- }
- return mManagesContexts;
- }
- 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;
- status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
- if (err < NO_ERROR) return NULL;
- }
- return &mHandleToObject.editItemAt(handle);
- }
- sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
- {
- sp<IBinder> result;
- AutoMutex _l(mLock);
- handle_entry* e = lookupHandleLocked(handle);
- if (e != NULL) {
- // We need to create a new BpBinder 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 (handle == 0) {
- // Special case for context manager...
- // The context manager is the only object for which we create
- // a BpBinder proxy without already holding a reference.
- // Perform a dummy transaction to ensure the context manager
- // is registered before we create the first local reference
- // to it (which will occur when creating the BpBinder).
- // If a local reference is created for the BpBinder when the
- // context manager is not present, the driver will fail to
- // provide a reference to the context manager, but the
- // driver API does not return status.
- //
- // Note that this is not race-free if the context manager
- // dies while this code runs.
- //
- // TODO: add a driver API to wait for context manager, or
- // stop special casing handle 0 for context manager and add
- // a driver API to get a handle to the context manager with
- // proper reference counting.
- Parcel data;
- status_t status = IPCThreadState::self()->transact(
- 0, IBinder::PING_TRANSACTION, data, NULL, 0);
- if (status == DEAD_OBJECT)
- return NULL;
- }
- b = new BpBinder(handle);
- e->binder = b;
- if (b) e->refs = b->getWeakRefs();
- result = b;
- } else {
- // This little bit of nastyness is to allow us to add a primary
- // reference to the remote proxy when this team doesn't have one
- // but another team is sending the handle to us.
- result.force_set(b);
- e->refs->decWeak(this);
- }
- }
- return result;
- }
- wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle)
- {
- wp<IBinder> result;
- AutoMutex _l(mLock);
- handle_entry* e = lookupHandleLocked(handle);
- if (e != NULL) {
- // We need to create a new BpBinder 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 BpBinder destructor will always
- // call expungeHandle(), which acquires the same lock we are holding now.
- // We need to do this because there is a race condition between someone
- // releasing a reference on this BpBinder, and a new reference on its handle
- // arriving from the driver.
- IBinder* b = e->binder;
- if (b == NULL || !e->refs->attemptIncWeak(this)) {
- b = new BpBinder(handle);
- result = b;
- e->binder = b;
- if (b) e->refs = b->getWeakRefs();
- } else {
- result = b;
- e->refs->decWeak(this);
- }
- }
- return result;
- }
- void ProcessState::expungeHandle(int32_t handle, IBinder* binder)
- {
- AutoMutex _l(mLock);
-
- handle_entry* e = lookupHandleLocked(handle);
- // This handle may have already been replaced with a new BpBinder
- // (if someone failed the AttemptIncWeak() above); we don't want
- // to overwrite it.
- if (e && e->binder == binder) e->binder = NULL;
- }
- String8 ProcessState::makeBinderThreadName() {
- int32_t s = android_atomic_add(1, &mThreadPoolSeq);
- String8 name;
- name.appendFormat("Binder_%X", s);
- return name;
- }
- void ProcessState::spawnPooledThread(bool isMain)
- {
- if (mThreadPoolStarted) {
- String8 name = makeBinderThreadName();
- ALOGV("Spawning new pooled thread, name=%s\n", name.string());
- sp<Thread> t = new PoolThread(isMain);
- t->run(name.string());
- }
- }
- status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
- status_t result = NO_ERROR;
- if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) != -1) {
- mMaxThreads = maxThreads;
- } else {
- result = -errno;
- ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
- }
- return result;
- }
- void ProcessState::giveThreadPoolName() {
- androidSetThreadName( makeBinderThreadName().string() );
- }
- static int open_driver()
- {
- int fd = open("/dev/binder", O_RDWR);
- if (fd >= 0) {
- fcntl(fd, F_SETFD, FD_CLOEXEC);
- int vers = 0;
- status_t result = ioctl(fd, BINDER_VERSION, &vers);
- if (result == -1) {
- ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
- close(fd);
- fd = -1;
- }
- if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
- ALOGE("Binder driver protocol does not match user space protocol!");
- close(fd);
- fd = -1;
- }
- size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
- result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
- if (result == -1) {
- ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
- }
- } else {
- ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
- }
- return fd;
- }
- ProcessState::ProcessState()
- : mDriverFD(open_driver())
- , mVMStart(MAP_FAILED)
- , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
- , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
- , mExecutingThreadsCount(0)
- , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
- , mManagesContexts(false)
- , mBinderContextCheckFunc(NULL)
- , mBinderContextUserData(NULL)
- , mThreadPoolStarted(false)
- , mThreadPoolSeq(1)
- {
- if (mDriverFD >= 0) {
- // XXX Ideally, there should be a specific define for whether we
- // have mmap (or whether we could possibly have the kernel module
- // availabla).
- #if !defined(HAVE_WIN32_IPC)
- // mmap the binder, providing a chunk of virtual address space to receive transactions.
- mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
- if (mVMStart == MAP_FAILED) {
- // *sigh*
- ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
- close(mDriverFD);
- mDriverFD = -1;
- }
- #else
- mDriverFD = -1;
- #endif
- }
- LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
- }
- ProcessState::~ProcessState()
- {
- }
-
- }; // namespace android
|