diff options
Diffstat (limited to 'libs/utils/IPCThreadState.cpp')
-rw-r--r-- | libs/utils/IPCThreadState.cpp | 1030 |
1 files changed, 0 insertions, 1030 deletions
diff --git a/libs/utils/IPCThreadState.cpp b/libs/utils/IPCThreadState.cpp deleted file mode 100644 index 04ae142..0000000 --- a/libs/utils/IPCThreadState.cpp +++ /dev/null @@ -1,1030 +0,0 @@ -/* - * 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. - */ - -#include <utils/IPCThreadState.h> - -#include <utils/Binder.h> -#include <utils/BpBinder.h> -#include <utils/Debug.h> -#include <utils/Log.h> -#include <utils/TextOutput.h> -#include <utils/threads.h> - -#include <private/utils/binder_module.h> -#include <private/utils/Static.h> - -#include <sys/ioctl.h> -#include <signal.h> -#include <errno.h> -#include <stdio.h> -#include <unistd.h> - -#ifdef HAVE_PTHREADS -#include <pthread.h> -#include <sched.h> -#include <sys/resource.h> -#endif -#ifdef HAVE_WIN32_THREADS -#include <windows.h> -#endif - - -#if LOG_NDEBUG - -#define IF_LOG_TRANSACTIONS() if (false) -#define IF_LOG_COMMANDS() if (false) -#define LOG_REMOTEREFS(...) -#define IF_LOG_REMOTEREFS() if (false) -#define LOG_THREADPOOL(...) -#define LOG_ONEWAY(...) - -#else - -#define IF_LOG_TRANSACTIONS() IF_LOG(LOG_VERBOSE, "transact") -#define IF_LOG_COMMANDS() IF_LOG(LOG_VERBOSE, "ipc") -#define LOG_REMOTEREFS(...) LOG(LOG_DEBUG, "remoterefs", __VA_ARGS__) -#define IF_LOG_REMOTEREFS() IF_LOG(LOG_DEBUG, "remoterefs") -#define LOG_THREADPOOL(...) LOG(LOG_DEBUG, "threadpool", __VA_ARGS__) -#define LOG_ONEWAY(...) LOG(LOG_DEBUG, "ipc", __VA_ARGS__) - -#endif - -// --------------------------------------------------------------------------- - -namespace android { - -static const char* getReturnString(size_t idx); -static const char* getCommandString(size_t idx); -static const void* printReturnCommand(TextOutput& out, const void* _cmd); -static const void* printCommand(TextOutput& out, const void* _cmd); - -// This will result in a missing symbol failure if the IF_LOG_COMMANDS() -// conditionals don't get stripped... but that is probably what we want. -#if !LOG_NDEBUG -static const char *kReturnStrings[] = { -#if 1 /* TODO: error update strings */ - "unknown", -#else - "BR_OK", - "BR_TIMEOUT", - "BR_WAKEUP", - "BR_TRANSACTION", - "BR_REPLY", - "BR_ACQUIRE_RESULT", - "BR_DEAD_REPLY", - "BR_TRANSACTION_COMPLETE", - "BR_INCREFS", - "BR_ACQUIRE", - "BR_RELEASE", - "BR_DECREFS", - "BR_ATTEMPT_ACQUIRE", - "BR_EVENT_OCCURRED", - "BR_NOOP", - "BR_SPAWN_LOOPER", - "BR_FINISHED", - "BR_DEAD_BINDER", - "BR_CLEAR_DEATH_NOTIFICATION_DONE" -#endif -}; - -static const char *kCommandStrings[] = { -#if 1 /* TODO: error update strings */ - "unknown", -#else - "BC_NOOP", - "BC_TRANSACTION", - "BC_REPLY", - "BC_ACQUIRE_RESULT", - "BC_FREE_BUFFER", - "BC_TRANSACTION_COMPLETE", - "BC_INCREFS", - "BC_ACQUIRE", - "BC_RELEASE", - "BC_DECREFS", - "BC_INCREFS_DONE", - "BC_ACQUIRE_DONE", - "BC_ATTEMPT_ACQUIRE", - "BC_RETRIEVE_ROOT_OBJECT", - "BC_SET_THREAD_ENTRY", - "BC_REGISTER_LOOPER", - "BC_ENTER_LOOPER", - "BC_EXIT_LOOPER", - "BC_SYNC", - "BC_STOP_PROCESS", - "BC_STOP_SELF", - "BC_REQUEST_DEATH_NOTIFICATION", - "BC_CLEAR_DEATH_NOTIFICATION", - "BC_DEAD_BINDER_DONE" -#endif -}; - -static const char* getReturnString(size_t idx) -{ - if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[0])) - return kReturnStrings[idx]; - else - return "unknown"; -} - -static const char* getCommandString(size_t idx) -{ - if (idx < sizeof(kCommandStrings) / sizeof(kCommandStrings[0])) - return kCommandStrings[idx]; - else - return "unknown"; -} - -static const void* printBinderTransactionData(TextOutput& out, const void* data) -{ - const binder_transaction_data* btd = - (const binder_transaction_data*)data; - out << "target=" << btd->target.ptr << " (cookie " << btd->cookie << ")" << endl - << "code=" << TypeCode(btd->code) << ", flags=" << (void*)btd->flags << endl - << "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size - << " bytes)" << endl - << "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size - << " bytes)" << endl; - return btd+1; -} - -static const void* printReturnCommand(TextOutput& out, const void* _cmd) -{ - static const int32_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]); - - const int32_t* cmd = (const int32_t*)_cmd; - int32_t code = *cmd++; - if (code == BR_ERROR) { - out << "BR_ERROR: " << (void*)(*cmd++) << endl; - return cmd; - } else if (code < 0 || code >= N) { - out << "Unknown reply: " << code << endl; - return cmd; - } - - out << kReturnStrings[code]; - switch (code) { - case BR_TRANSACTION: - case BR_REPLY: { - out << ": " << indent; - cmd = (const int32_t *)printBinderTransactionData(out, cmd); - out << dedent; - } break; - - case BR_ACQUIRE_RESULT: { - const int32_t res = *cmd++; - out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)"); - } break; - - case BR_INCREFS: - case BR_ACQUIRE: - case BR_RELEASE: - case BR_DECREFS: { - const int32_t b = *cmd++; - const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c << ")"; - } break; - - case BR_ATTEMPT_ACQUIRE: { - const int32_t p = *cmd++; - const int32_t b = *cmd++; - const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c - << "), pri=" << p; - } break; - - case BR_DEAD_BINDER: - case BR_CLEAR_DEATH_NOTIFICATION_DONE: { - const int32_t c = *cmd++; - out << ": death cookie " << (void*)c; - } break; - } - - out << endl; - return cmd; -} - -static const void* printCommand(TextOutput& out, const void* _cmd) -{ - static const int32_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]); - - const int32_t* cmd = (const int32_t*)_cmd; - int32_t code = *cmd++; - if (code < 0 || code >= N) { - out << "Unknown command: " << code << endl; - return cmd; - } - - out << kCommandStrings[code]; - switch (code) { - case BC_TRANSACTION: - case BC_REPLY: { - out << ": " << indent; - cmd = (const int32_t *)printBinderTransactionData(out, cmd); - out << dedent; - } break; - - case BC_ACQUIRE_RESULT: { - const int32_t res = *cmd++; - out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)"); - } break; - - case BC_FREE_BUFFER: { - const int32_t buf = *cmd++; - out << ": buffer=" << (void*)buf; - } break; - - case BC_INCREFS: - case BC_ACQUIRE: - case BC_RELEASE: - case BC_DECREFS: { - const int32_t d = *cmd++; - out << ": descriptor=" << (void*)d; - } break; - - case BC_INCREFS_DONE: - case BC_ACQUIRE_DONE: { - const int32_t b = *cmd++; - const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c << ")"; - } break; - - case BC_ATTEMPT_ACQUIRE: { - const int32_t p = *cmd++; - const int32_t d = *cmd++; - out << ": decriptor=" << (void*)d << ", pri=" << p; - } break; - - case BC_REQUEST_DEATH_NOTIFICATION: - case BC_CLEAR_DEATH_NOTIFICATION: { - const int32_t h = *cmd++; - const int32_t c = *cmd++; - out << ": handle=" << h << " (death cookie " << (void*)c << ")"; - } break; - - case BC_DEAD_BINDER_DONE: { - const int32_t c = *cmd++; - out << ": death cookie " << (void*)c; - } break; - } - - out << endl; - return cmd; -} -#endif - -static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; -static bool gHaveTLS = false; -static pthread_key_t gTLS = 0; -static bool gShutdown = false; - -IPCThreadState* IPCThreadState::self() -{ - if (gHaveTLS) { -restart: - const pthread_key_t k = gTLS; - IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); - if (st) return st; - return new IPCThreadState; - } - - if (gShutdown) return NULL; - - pthread_mutex_lock(&gTLSMutex); - if (!gHaveTLS) { - if (pthread_key_create(&gTLS, threadDestructor) != 0) { - pthread_mutex_unlock(&gTLSMutex); - return NULL; - } - gHaveTLS = true; - } - pthread_mutex_unlock(&gTLSMutex); - goto restart; -} - -void IPCThreadState::shutdown() -{ - gShutdown = true; - - if (gHaveTLS) { - // XXX Need to wait for all thread pool threads to exit! - IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS); - if (st) { - delete st; - pthread_setspecific(gTLS, NULL); - } - gHaveTLS = false; - } -} - -sp<ProcessState> IPCThreadState::process() -{ - return mProcess; -} - -status_t IPCThreadState::clearLastError() -{ - const status_t err = mLastError; - mLastError = NO_ERROR; - return err; -} - -int IPCThreadState::getCallingPid() -{ - return mCallingPid; -} - -int IPCThreadState::getCallingUid() -{ - return mCallingUid; -} - -int64_t IPCThreadState::clearCallingIdentity() -{ - int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid; - clearCaller(); - return token; -} - -void IPCThreadState::restoreCallingIdentity(int64_t token) -{ - mCallingUid = (int)(token>>32); - mCallingPid = (int)token; -} - -void IPCThreadState::clearCaller() -{ - if (mProcess->supportsProcesses()) { - mCallingPid = getpid(); - mCallingUid = getuid(); - } else { - mCallingPid = -1; - mCallingUid = -1; - } -} - -void IPCThreadState::flushCommands() -{ - if (mProcess->mDriverFD <= 0) - return; - talkWithDriver(false); -} - -void IPCThreadState::joinThreadPool(bool isMain) -{ - LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); - - mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); - - status_t result; - do { - int32_t cmd; - - // When we've cleared the incoming command queue, process any pending derefs - if (mIn.dataPosition() >= mIn.dataSize()) { - size_t numPending = mPendingWeakDerefs.size(); - if (numPending > 0) { - for (size_t i = 0; i < numPending; i++) { - RefBase::weakref_type* refs = mPendingWeakDerefs[i]; - refs->decWeak(mProcess.get()); - } - mPendingWeakDerefs.clear(); - } - - numPending = mPendingStrongDerefs.size(); - if (numPending > 0) { - for (size_t i = 0; i < numPending; i++) { - BBinder* obj = mPendingStrongDerefs[i]; - obj->decStrong(mProcess.get()); - } - mPendingStrongDerefs.clear(); - } - } - - // now get the next command to be processed, waiting if necessary - result = talkWithDriver(); - if (result >= NO_ERROR) { - size_t IN = mIn.dataAvail(); - if (IN < sizeof(int32_t)) continue; - cmd = mIn.readInt32(); - IF_LOG_COMMANDS() { - alog << "Processing top-level Command: " - << getReturnString(cmd) << endl; - } - result = executeCommand(cmd); - } - - // Let this thread exit the thread pool if it is no longer - // needed and it is not the main process thread. - if(result == TIMED_OUT && !isMain) { - break; - } - } while (result != -ECONNREFUSED && result != -EBADF); - - LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n", - (void*)pthread_self(), getpid(), (void*)result); - - mOut.writeInt32(BC_EXIT_LOOPER); - talkWithDriver(false); -} - -void IPCThreadState::stopProcess(bool immediate) -{ - //LOGI("**** STOPPING PROCESS"); - flushCommands(); - int fd = mProcess->mDriverFD; - mProcess->mDriverFD = -1; - close(fd); - //kill(getpid(), SIGKILL); -} - -status_t IPCThreadState::transact(int32_t handle, - uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags) -{ - status_t err = data.errorCheck(); - - flags |= TF_ACCEPT_FDS; - - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " - << handle << " / code " << TypeCode(code) << ": " - << indent << data << dedent << endl; - } - - if (err == NO_ERROR) { - LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(), - (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY"); - err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); - } - - if (err != NO_ERROR) { - if (reply) reply->setError(err); - return (mLastError = err); - } - - if ((flags & TF_ONE_WAY) == 0) { - if (reply) { - err = waitForResponse(reply); - } else { - Parcel fakeReply; - err = waitForResponse(&fakeReply); - } - - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand " - << handle << ": "; - if (reply) alog << indent << *reply << dedent << endl; - else alog << "(none requested)" << endl; - } - } else { - err = waitForResponse(NULL, NULL); - } - - return err; -} - -void IPCThreadState::incStrongHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::incStrongHandle(%d)\n", handle); - mOut.writeInt32(BC_ACQUIRE); - mOut.writeInt32(handle); -} - -void IPCThreadState::decStrongHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::decStrongHandle(%d)\n", handle); - mOut.writeInt32(BC_RELEASE); - mOut.writeInt32(handle); -} - -void IPCThreadState::incWeakHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle); - mOut.writeInt32(BC_INCREFS); - mOut.writeInt32(handle); -} - -void IPCThreadState::decWeakHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::decWeakHandle(%d)\n", handle); - mOut.writeInt32(BC_DECREFS); - mOut.writeInt32(handle); -} - -status_t IPCThreadState::attemptIncStrongHandle(int32_t handle) -{ - mOut.writeInt32(BC_ATTEMPT_ACQUIRE); - mOut.writeInt32(0); // xxx was thread priority - mOut.writeInt32(handle); - status_t result = UNKNOWN_ERROR; - - waitForResponse(NULL, &result); - -#if LOG_REFCOUNTS - printf("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n", - handle, result == NO_ERROR ? "SUCCESS" : "FAILURE"); -#endif - - return result; -} - -void IPCThreadState::expungeHandle(int32_t handle, IBinder* binder) -{ -#if LOG_REFCOUNTS - printf("IPCThreadState::expungeHandle(%ld)\n", handle); -#endif - self()->mProcess->expungeHandle(handle, binder); -} - -status_t IPCThreadState::requestDeathNotification(int32_t handle, BpBinder* proxy) -{ - mOut.writeInt32(BC_REQUEST_DEATH_NOTIFICATION); - mOut.writeInt32((int32_t)handle); - mOut.writeInt32((int32_t)proxy); - return NO_ERROR; -} - -status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) -{ - mOut.writeInt32(BC_CLEAR_DEATH_NOTIFICATION); - mOut.writeInt32((int32_t)handle); - mOut.writeInt32((int32_t)proxy); - return NO_ERROR; -} - -IPCThreadState::IPCThreadState() - : mProcess(ProcessState::self()) -{ - pthread_setspecific(gTLS, this); - clearCaller(); - mIn.setDataCapacity(256); - mOut.setDataCapacity(256); -} - -IPCThreadState::~IPCThreadState() -{ -} - -status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags) -{ - status_t err; - status_t statusBuffer; - err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer); - if (err < NO_ERROR) return err; - - return waitForResponse(NULL, NULL); -} - -status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) -{ - int32_t cmd; - int32_t err; - - while (1) { - if ((err=talkWithDriver()) < NO_ERROR) break; - err = mIn.errorCheck(); - if (err < NO_ERROR) break; - if (mIn.dataAvail() == 0) continue; - - cmd = mIn.readInt32(); - - IF_LOG_COMMANDS() { - alog << "Processing waitForResponse Command: " - << getReturnString(cmd) << endl; - } - - switch (cmd) { - case BR_TRANSACTION_COMPLETE: - if (!reply && !acquireResult) goto finish; - break; - - case BR_DEAD_REPLY: - err = DEAD_OBJECT; - goto finish; - - case BR_FAILED_REPLY: - err = FAILED_TRANSACTION; - goto finish; - - case BR_ACQUIRE_RESULT: - { - LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT"); - const int32_t result = mIn.readInt32(); - if (!acquireResult) continue; - *acquireResult = result ? NO_ERROR : INVALID_OPERATION; - } - goto finish; - - case BR_REPLY: - { - binder_transaction_data tr; - err = mIn.read(&tr, sizeof(tr)); - LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY"); - if (err != NO_ERROR) goto finish; - - if (reply) { - if ((tr.flags & TF_STATUS_CODE) == 0) { - reply->ipcSetDataReference( - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), - freeBuffer, this); - } else { - err = *static_cast<const status_t*>(tr.data.ptr.buffer); - freeBuffer(NULL, - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), this); - } - } else { - freeBuffer(NULL, - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), this); - continue; - } - } - goto finish; - - default: - err = executeCommand(cmd); - if (err != NO_ERROR) goto finish; - break; - } - } - -finish: - if (err != NO_ERROR) { - if (acquireResult) *acquireResult = err; - if (reply) reply->setError(err); - mLastError = err; - } - - return err; -} - -status_t IPCThreadState::talkWithDriver(bool doReceive) -{ - LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened"); - - binder_write_read bwr; - - // Is the read buffer empty? - const bool needRead = mIn.dataPosition() >= mIn.dataSize(); - - // We don't want to write anything if we are still reading - // from data left in the input buffer and the caller - // has requested to read the next data. - const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; - - bwr.write_size = outAvail; - bwr.write_buffer = (long unsigned int)mOut.data(); - - // This is what we'll read. - if (doReceive && needRead) { - bwr.read_size = mIn.dataCapacity(); - bwr.read_buffer = (long unsigned int)mIn.data(); - } else { - bwr.read_size = 0; - } - - IF_LOG_COMMANDS() { - TextOutput::Bundle _b(alog); - if (outAvail != 0) { - alog << "Sending commands to driver: " << indent; - const void* cmds = (const void*)bwr.write_buffer; - const void* end = ((const uint8_t*)cmds)+bwr.write_size; - alog << HexDump(cmds, bwr.write_size) << endl; - while (cmds < end) cmds = printCommand(alog, cmds); - alog << dedent; - } - alog << "Size of receive buffer: " << bwr.read_size - << ", needRead: " << needRead << ", doReceive: " << doReceive << endl; - } - - // Return immediately if there is nothing to do. - if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR; - - bwr.write_consumed = 0; - bwr.read_consumed = 0; - status_t err; - do { - IF_LOG_COMMANDS() { - alog << "About to read/write, write size = " << mOut.dataSize() << endl; - } -#if defined(HAVE_ANDROID_OS) - if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) - err = NO_ERROR; - else - err = -errno; -#else - err = INVALID_OPERATION; -#endif - IF_LOG_COMMANDS() { - alog << "Finished read/write, write size = " << mOut.dataSize() << endl; - } - } while (err == -EINTR); - - IF_LOG_COMMANDS() { - alog << "Our err: " << (void*)err << ", write consumed: " - << bwr.write_consumed << " (of " << mOut.dataSize() - << "), read consumed: " << bwr.read_consumed << endl; - } - - if (err >= NO_ERROR) { - if (bwr.write_consumed > 0) { - if (bwr.write_consumed < (ssize_t)mOut.dataSize()) - mOut.remove(0, bwr.write_consumed); - else - mOut.setDataSize(0); - } - if (bwr.read_consumed > 0) { - mIn.setDataSize(bwr.read_consumed); - mIn.setDataPosition(0); - } - IF_LOG_COMMANDS() { - TextOutput::Bundle _b(alog); - alog << "Remaining data size: " << mOut.dataSize() << endl; - alog << "Received commands from driver: " << indent; - const void* cmds = mIn.data(); - const void* end = mIn.data() + mIn.dataSize(); - alog << HexDump(cmds, mIn.dataSize()) << endl; - while (cmds < end) cmds = printReturnCommand(alog, cmds); - alog << dedent; - } - return NO_ERROR; - } - - return err; -} - -status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, - int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) -{ - binder_transaction_data tr; - - tr.target.handle = handle; - tr.code = code; - tr.flags = binderFlags; - - const status_t err = data.errorCheck(); - if (err == NO_ERROR) { - tr.data_size = data.ipcDataSize(); - tr.data.ptr.buffer = data.ipcData(); - tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t); - tr.data.ptr.offsets = data.ipcObjects(); - } else if (statusBuffer) { - tr.flags |= TF_STATUS_CODE; - *statusBuffer = err; - tr.data_size = sizeof(status_t); - tr.data.ptr.buffer = statusBuffer; - tr.offsets_size = 0; - tr.data.ptr.offsets = NULL; - } else { - return (mLastError = err); - } - - mOut.writeInt32(cmd); - mOut.write(&tr, sizeof(tr)); - - return NO_ERROR; -} - -sp<BBinder> the_context_object; - -void setTheContextObject(sp<BBinder> obj) -{ - the_context_object = obj; -} - -status_t IPCThreadState::executeCommand(int32_t cmd) -{ - BBinder* obj; - RefBase::weakref_type* refs; - status_t result = NO_ERROR; - - switch (cmd) { - case BR_ERROR: - result = mIn.readInt32(); - break; - - case BR_OK: - break; - - case BR_ACQUIRE: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - LOG_ASSERT(refs->refBase() == obj, - "BR_ACQUIRE: object %p does not match cookie %p (expected %p)", - refs, obj, refs->refBase()); - obj->incStrong(mProcess.get()); - IF_LOG_REMOTEREFS() { - LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj); - obj->printRefs(); - } - mOut.writeInt32(BC_ACQUIRE_DONE); - mOut.writeInt32((int32_t)refs); - mOut.writeInt32((int32_t)obj); - break; - - case BR_RELEASE: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - LOG_ASSERT(refs->refBase() == obj, - "BR_RELEASE: object %p does not match cookie %p (expected %p)", - refs, obj, refs->refBase()); - IF_LOG_REMOTEREFS() { - LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj); - obj->printRefs(); - } - mPendingStrongDerefs.push(obj); - break; - - case BR_INCREFS: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - refs->incWeak(mProcess.get()); - mOut.writeInt32(BC_INCREFS_DONE); - mOut.writeInt32((int32_t)refs); - mOut.writeInt32((int32_t)obj); - break; - - case BR_DECREFS: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - // NOTE: This assertion is not valid, because the object may no - // longer exist (thus the (BBinder*)cast above resulting in a different - // memory address). - //LOG_ASSERT(refs->refBase() == obj, - // "BR_DECREFS: object %p does not match cookie %p (expected %p)", - // refs, obj, refs->refBase()); - mPendingWeakDerefs.push(refs); - break; - - case BR_ATTEMPT_ACQUIRE: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - - { - const bool success = refs->attemptIncStrong(mProcess.get()); - LOG_ASSERT(success && refs->refBase() == obj, - "BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)", - refs, obj, refs->refBase()); - - mOut.writeInt32(BC_ACQUIRE_RESULT); - mOut.writeInt32((int32_t)success); - } - break; - - case BR_TRANSACTION: - { - binder_transaction_data tr; - result = mIn.read(&tr, sizeof(tr)); - LOG_ASSERT(result == NO_ERROR, - "Not enough command data for brTRANSACTION"); - if (result != NO_ERROR) break; - - Parcel buffer; - buffer.ipcSetDataReference( - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), freeBuffer, this); - - const pid_t origPid = mCallingPid; - const uid_t origUid = mCallingUid; - - mCallingPid = tr.sender_pid; - mCallingUid = tr.sender_euid; - - //LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid); - - Parcel reply; - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BR_TRANSACTION thr " << (void*)pthread_self() - << " / obj " << tr.target.ptr << " / code " - << TypeCode(tr.code) << ": " << indent << buffer - << dedent << endl - << "Data addr = " - << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer) - << ", offsets addr=" - << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl; - } - if (tr.target.ptr) { - sp<BBinder> b((BBinder*)tr.cookie); - const status_t error = b->transact(tr.code, buffer, &reply, 0); - if (error < NO_ERROR) reply.setError(error); - - } else { - const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0); - if (error < NO_ERROR) reply.setError(error); - } - - //LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n", - // mCallingPid, origPid, origUid); - - if ((tr.flags & TF_ONE_WAY) == 0) { - LOG_ONEWAY("Sending reply to %d!", mCallingPid); - sendReply(reply, 0); - } else { - LOG_ONEWAY("NOT sending reply to %d!", mCallingPid); - } - - mCallingPid = origPid; - mCallingUid = origUid; - - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj " - << tr.target.ptr << ": " << indent << reply << dedent << endl; - } - - } - break; - - case BR_DEAD_BINDER: - { - BpBinder *proxy = (BpBinder*)mIn.readInt32(); - proxy->sendObituary(); - mOut.writeInt32(BC_DEAD_BINDER_DONE); - mOut.writeInt32((int32_t)proxy); - } break; - - case BR_CLEAR_DEATH_NOTIFICATION_DONE: - { - BpBinder *proxy = (BpBinder*)mIn.readInt32(); - proxy->getWeakRefs()->decWeak(proxy); - } break; - - case BR_FINISHED: - result = TIMED_OUT; - break; - - case BR_NOOP: - break; - - case BR_SPAWN_LOOPER: - mProcess->spawnPooledThread(false); - break; - - default: - printf("*** BAD COMMAND %d received from Binder driver\n", cmd); - result = UNKNOWN_ERROR; - break; - } - - if (result != NO_ERROR) { - mLastError = result; - } - - return result; -} - -void IPCThreadState::threadDestructor(void *st) -{ - IPCThreadState* const self = static_cast<IPCThreadState*>(st); - if (self) { - self->flushCommands(); -#if defined(HAVE_ANDROID_OS) - ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0); -#endif - delete self; - } -} - - -void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data, size_t dataSize, - const size_t* objects, size_t objectsSize, - void* cookie) -{ - //LOGI("Freeing parcel %p", &parcel); - IF_LOG_COMMANDS() { - alog << "Writing BC_FREE_BUFFER for " << data << endl; - } - LOG_ASSERT(data != NULL, "Called with NULL data"); - if (parcel != NULL) parcel->closeFileDescriptors(); - IPCThreadState* state = self(); - state->mOut.writeInt32(BC_FREE_BUFFER); - state->mOut.writeInt32((int32_t)data); -} - -}; // namespace android |