12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196 |
- /*
- * 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 "IPCThreadState"
- #include <binder/IPCThreadState.h>
- #include <binder/Binder.h>
- #include <binder/BpBinder.h>
- #include <binder/TextOutput.h>
- #include <cutils/sched_policy.h>
- #include <utils/Log.h>
- #include <utils/threads.h>
- #include <private/binder/binder_module.h>
- #include <private/binder/Static.h>
- #include <errno.h>
- #include <pthread.h>
- #include <sched.h>
- #include <signal.h>
- #include <stdio.h>
- #include <sys/ioctl.h>
- #include <sys/resource.h>
- #include <unistd.h>
- #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_ALOG(LOG_VERBOSE, "transact")
- #define IF_LOG_COMMANDS() IF_ALOG(LOG_VERBOSE, "ipc")
- #define LOG_REMOTEREFS(...) ALOG(LOG_DEBUG, "remoterefs", __VA_ARGS__)
- #define IF_LOG_REMOTEREFS() IF_ALOG(LOG_DEBUG, "remoterefs")
- #define LOG_THREADPOOL(...) ALOG(LOG_DEBUG, "threadpool", __VA_ARGS__)
- #define LOG_ONEWAY(...) ALOG(LOG_DEBUG, "ipc", __VA_ARGS__)
- #endif
- // ---------------------------------------------------------------------------
- namespace android {
- static const char* getReturnString(size_t idx);
- static const void* printReturnCommand(TextOutput& out, const void* _cmd);
- static const void* printCommand(TextOutput& out, const void* _cmd);
- // Static const and functions will be optimized out if not used,
- // when LOG_NDEBUG and references in IF_LOG_COMMANDS() are optimized out.
- static const char *kReturnStrings[] = {
- "BR_ERROR",
- "BR_OK",
- "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_NOOP",
- "BR_SPAWN_LOOPER",
- "BR_FINISHED",
- "BR_DEAD_BINDER",
- "BR_CLEAR_DEATH_NOTIFICATION_DONE",
- "BR_FAILED_REPLY"
- };
- static const char *kCommandStrings[] = {
- "BC_TRANSACTION",
- "BC_REPLY",
- "BC_ACQUIRE_RESULT",
- "BC_FREE_BUFFER",
- "BC_INCREFS",
- "BC_ACQUIRE",
- "BC_RELEASE",
- "BC_DECREFS",
- "BC_INCREFS_DONE",
- "BC_ACQUIRE_DONE",
- "BC_ATTEMPT_ACQUIRE",
- "BC_REGISTER_LOOPER",
- "BC_ENTER_LOOPER",
- "BC_EXIT_LOOPER",
- "BC_REQUEST_DEATH_NOTIFICATION",
- "BC_CLEAR_DEATH_NOTIFICATION",
- "BC_DEAD_BINDER_DONE"
- };
- static const char* getReturnString(size_t idx)
- {
- if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[0]))
- return kReturnStrings[idx];
- else
- return "unknown";
- }
- static const void* printBinderTransactionData(TextOutput& out, const void* data)
- {
- const binder_transaction_data* btd =
- (const binder_transaction_data*)data;
- if (btd->target.handle < 1024) {
- /* want to print descriptors in decimal; guess based on value */
- out << "target.desc=" << btd->target.handle;
- } else {
- out << "target.ptr=" << btd->target.ptr;
- }
- out << " (cookie " << btd->cookie << ")" << endl
- << "code=" << TypeCode(btd->code) << ", flags=" << (void*)(long)btd->flags << endl
- << "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size
- << " bytes)" << endl
- << "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size
- << " bytes)";
- return btd+1;
- }
- static const void* printReturnCommand(TextOutput& out, const void* _cmd)
- {
- static const size_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]);
- const int32_t* cmd = (const int32_t*)_cmd;
- uint32_t code = (uint32_t)*cmd++;
- size_t cmdIndex = code & 0xff;
- if (code == BR_ERROR) {
- out << "BR_ERROR: " << (void*)(long)(*cmd++) << endl;
- return cmd;
- } else if (cmdIndex >= N) {
- out << "Unknown reply: " << code << endl;
- return cmd;
- }
- out << kReturnStrings[cmdIndex];
-
- 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*)(long)b << " (cookie " << (void*)(long)c << ")";
- } break;
-
- case BR_ATTEMPT_ACQUIRE: {
- const int32_t p = *cmd++;
- const int32_t b = *cmd++;
- const int32_t c = *cmd++;
- out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c
- << "), pri=" << p;
- } break;
- case BR_DEAD_BINDER:
- case BR_CLEAR_DEATH_NOTIFICATION_DONE: {
- const int32_t c = *cmd++;
- out << ": death cookie " << (void*)(long)c;
- } break;
- default:
- // no details to show for: BR_OK, BR_DEAD_REPLY,
- // BR_TRANSACTION_COMPLETE, BR_FINISHED
- break;
- }
-
- out << endl;
- return cmd;
- }
- static const void* printCommand(TextOutput& out, const void* _cmd)
- {
- static const size_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]);
- const int32_t* cmd = (const int32_t*)_cmd;
- uint32_t code = (uint32_t)*cmd++;
- size_t cmdIndex = code & 0xff;
- if (cmdIndex >= N) {
- out << "Unknown command: " << code << endl;
- return cmd;
- }
- out << kCommandStrings[cmdIndex];
- 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*)(long)buf;
- } break;
-
- case BC_INCREFS:
- case BC_ACQUIRE:
- case BC_RELEASE:
- case BC_DECREFS: {
- const int32_t d = *cmd++;
- out << ": desc=" << d;
- } break;
-
- case BC_INCREFS_DONE:
- case BC_ACQUIRE_DONE: {
- const int32_t b = *cmd++;
- const int32_t c = *cmd++;
- out << ": target=" << (void*)(long)b << " (cookie " << (void*)(long)c << ")";
- } break;
-
- case BC_ATTEMPT_ACQUIRE: {
- const int32_t p = *cmd++;
- const int32_t d = *cmd++;
- out << ": desc=" << 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*)(long)c << ")";
- } break;
- case BC_DEAD_BINDER_DONE: {
- const int32_t c = *cmd++;
- out << ": death cookie " << (void*)(long)c;
- } break;
- default:
- // no details to show for: BC_REGISTER_LOOPER, BC_ENTER_LOOPER,
- // BC_EXIT_LOOPER
- break;
- }
-
- out << endl;
- return cmd;
- }
- static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
- static bool gHaveTLS = false;
- static pthread_key_t gTLS = 0;
- static bool gShutdown = false;
- static bool gDisableBackgroundScheduling = 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;
- }
- IPCThreadState* IPCThreadState::selfOrNull()
- {
- if (gHaveTLS) {
- const pthread_key_t k = gTLS;
- IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
- return st;
- }
- return NULL;
- }
- 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;
- }
- }
- void IPCThreadState::disableBackgroundScheduling(bool disable)
- {
- gDisableBackgroundScheduling = disable;
- }
- sp<ProcessState> IPCThreadState::process()
- {
- return mProcess;
- }
- status_t IPCThreadState::clearLastError()
- {
- const status_t err = mLastError;
- mLastError = NO_ERROR;
- return err;
- }
- pid_t IPCThreadState::getCallingPid() const
- {
- return mCallingPid;
- }
- uid_t IPCThreadState::getCallingUid() const
- {
- return mCallingUid;
- }
- int64_t IPCThreadState::clearCallingIdentity()
- {
- int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid;
- clearCaller();
- return token;
- }
- void IPCThreadState::setStrictModePolicy(int32_t policy)
- {
- mStrictModePolicy = policy;
- }
- int32_t IPCThreadState::getStrictModePolicy() const
- {
- return mStrictModePolicy;
- }
- void IPCThreadState::setLastTransactionBinderFlags(int32_t flags)
- {
- mLastTransactionBinderFlags = flags;
- }
- int32_t IPCThreadState::getLastTransactionBinderFlags() const
- {
- return mLastTransactionBinderFlags;
- }
- void IPCThreadState::restoreCallingIdentity(int64_t token)
- {
- mCallingUid = (int)(token>>32);
- mCallingPid = (int)token;
- }
- void IPCThreadState::clearCaller()
- {
- mCallingPid = getpid();
- mCallingUid = getuid();
- }
- void IPCThreadState::flushCommands()
- {
- if (mProcess->mDriverFD <= 0)
- return;
- talkWithDriver(false);
- }
- void IPCThreadState::blockUntilThreadAvailable()
- {
- pthread_mutex_lock(&mProcess->mThreadCountLock);
- while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) {
- ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%lu mMaxThreads=%lu\n",
- static_cast<unsigned long>(mProcess->mExecutingThreadsCount),
- static_cast<unsigned long>(mProcess->mMaxThreads));
- pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock);
- }
- pthread_mutex_unlock(&mProcess->mThreadCountLock);
- }
- status_t IPCThreadState::getAndExecuteCommand()
- {
- status_t result;
- int32_t cmd;
- result = talkWithDriver();
- if (result >= NO_ERROR) {
- size_t IN = mIn.dataAvail();
- if (IN < sizeof(int32_t)) return result;
- cmd = mIn.readInt32();
- IF_LOG_COMMANDS() {
- alog << "Processing top-level Command: "
- << getReturnString(cmd) << endl;
- }
- pthread_mutex_lock(&mProcess->mThreadCountLock);
- mProcess->mExecutingThreadsCount++;
- pthread_mutex_unlock(&mProcess->mThreadCountLock);
- result = executeCommand(cmd);
- pthread_mutex_lock(&mProcess->mThreadCountLock);
- mProcess->mExecutingThreadsCount--;
- pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
- pthread_mutex_unlock(&mProcess->mThreadCountLock);
- // After executing the command, ensure that the thread is returned to the
- // foreground cgroup before rejoining the pool. The driver takes care of
- // restoring the priority, but doesn't do anything with cgroups so we
- // need to take care of that here in userspace. Note that we do make
- // sure to go in the foreground after executing a transaction, but
- // there are other callbacks into user code that could have changed
- // our group so we want to make absolutely sure it is put back.
- set_sched_policy(mMyThreadId, SP_FOREGROUND);
- }
- return result;
- }
- // When we've cleared the incoming command queue, process any pending derefs
- void IPCThreadState::processPendingDerefs()
- {
- 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();
- }
- }
- }
- 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);
-
- // This thread may have been spawned by a thread that was in the background
- // scheduling group, so first we will make sure it is in the foreground
- // one to avoid performing an initial transaction in the background.
- set_sched_policy(mMyThreadId, SP_FOREGROUND);
-
- status_t result;
- do {
- processPendingDerefs();
- // now get the next command to be processed, waiting if necessary
- result = getAndExecuteCommand();
- if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
- ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
- mProcess->mDriverFD, result);
- abort();
- }
-
- // 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);
- }
- int IPCThreadState::setupPolling(int* fd)
- {
- if (mProcess->mDriverFD <= 0) {
- return -EBADF;
- }
- mOut.writeInt32(BC_ENTER_LOOPER);
- *fd = mProcess->mDriverFD;
- return 0;
- }
- status_t IPCThreadState::handlePolledCommands()
- {
- status_t result;
- do {
- result = getAndExecuteCommand();
- } while (mIn.dataPosition() < mIn.dataSize());
- processPendingDerefs();
- flushCommands();
- return result;
- }
- void IPCThreadState::stopProcess(bool /*immediate*/)
- {
- //ALOGI("**** 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 0
- if (code == 4) { // relayout
- ALOGI(">>>>>> CALLING transaction 4");
- } else {
- ALOGI(">>>>>> CALLING transaction %d", code);
- }
- #endif
- if (reply) {
- err = waitForResponse(reply);
- } else {
- Parcel fakeReply;
- err = waitForResponse(&fakeReply);
- }
- #if 0
- if (code == 4) { // relayout
- ALOGI("<<<<<< RETURNING transaction 4");
- } else {
- ALOGI("<<<<<< RETURNING transaction %d", code);
- }
- #endif
-
- 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)
- {
- #if HAS_BC_ATTEMPT_ACQUIRE
- LOG_REMOTEREFS("IPCThreadState::attemptIncStrongHandle(%d)\n", 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;
- #else
- (void)handle;
- ALOGE("%s(%d): Not supported\n", __func__, handle);
- return INVALID_OPERATION;
- #endif
- }
- 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.writePointer((uintptr_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.writePointer((uintptr_t)proxy);
- return NO_ERROR;
- }
- IPCThreadState::IPCThreadState()
- : mProcess(ProcessState::self()),
- mMyThreadId(gettid()),
- mStrictModePolicy(0),
- mLastTransactionBinderFlags(0)
- {
- 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)
- {
- uint32_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 = (uint32_t)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:
- {
- ALOG_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));
- ALOG_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 binder_size_t*>(tr.data.ptr.offsets),
- tr.offsets_size/sizeof(binder_size_t),
- freeBuffer, this);
- } else {
- err = *reinterpret_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 binder_size_t*>(tr.data.ptr.offsets),
- tr.offsets_size/sizeof(binder_size_t), this);
- }
- } else {
- freeBuffer(NULL,
- reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
- tr.data_size,
- reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
- tr.offsets_size/sizeof(binder_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)
- {
- if (mProcess->mDriverFD <= 0) {
- return -EBADF;
- }
-
- 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 = (uintptr_t)mOut.data();
- // This is what we'll read.
- if (doReceive && needRead) {
- bwr.read_size = mIn.dataCapacity();
- bwr.read_buffer = (uintptr_t)mIn.data();
- } else {
- bwr.read_size = 0;
- bwr.read_buffer = 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 (mProcess->mDriverFD <= 0) {
- err = -EBADF;
- }
- IF_LOG_COMMANDS() {
- alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
- }
- } while (err == -EINTR);
- IF_LOG_COMMANDS() {
- alog << "Our err: " << (void*)(intptr_t)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 < 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.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
- tr.target.handle = handle;
- tr.code = code;
- tr.flags = binderFlags;
- tr.cookie = 0;
- tr.sender_pid = 0;
- tr.sender_euid = 0;
-
- 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(binder_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 = reinterpret_cast<uintptr_t>(statusBuffer);
- tr.offsets_size = 0;
- tr.data.ptr.offsets = 0;
- } 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 ((uint32_t)cmd) {
- case BR_ERROR:
- result = mIn.readInt32();
- break;
-
- case BR_OK:
- break;
-
- case BR_ACQUIRE:
- refs = (RefBase::weakref_type*)mIn.readPointer();
- obj = (BBinder*)mIn.readPointer();
- ALOG_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.writePointer((uintptr_t)refs);
- mOut.writePointer((uintptr_t)obj);
- break;
-
- case BR_RELEASE:
- refs = (RefBase::weakref_type*)mIn.readPointer();
- obj = (BBinder*)mIn.readPointer();
- ALOG_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.readPointer();
- obj = (BBinder*)mIn.readPointer();
- refs->incWeak(mProcess.get());
- mOut.writeInt32(BC_INCREFS_DONE);
- mOut.writePointer((uintptr_t)refs);
- mOut.writePointer((uintptr_t)obj);
- break;
-
- case BR_DECREFS:
- refs = (RefBase::weakref_type*)mIn.readPointer();
- obj = (BBinder*)mIn.readPointer();
- // NOTE: This assertion is not valid, because the object may no
- // longer exist (thus the (BBinder*)cast above resulting in a different
- // memory address).
- //ALOG_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.readPointer();
- obj = (BBinder*)mIn.readPointer();
-
- {
- const bool success = refs->attemptIncStrong(mProcess.get());
- ALOG_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));
- ALOG_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 binder_size_t*>(tr.data.ptr.offsets),
- tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
-
- const pid_t origPid = mCallingPid;
- const uid_t origUid = mCallingUid;
- const int32_t origStrictModePolicy = mStrictModePolicy;
- const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags;
- mCallingPid = tr.sender_pid;
- mCallingUid = tr.sender_euid;
- mLastTransactionBinderFlags = tr.flags;
- int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
- if (gDisableBackgroundScheduling) {
- if (curPrio > ANDROID_PRIORITY_NORMAL) {
- // We have inherited a reduced priority from the caller, but do not
- // want to run in that state in this process. The driver set our
- // priority already (though not our scheduling class), so bounce
- // it back to the default before invoking the transaction.
- setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
- }
- } else {
- if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
- // We want to use the inherited priority from the caller.
- // Ensure this thread is in the background scheduling class,
- // since the driver won't modify scheduling classes for us.
- // The scheduling group is reset to default by the caller
- // once this method returns after the transaction is complete.
- set_sched_policy(mMyThreadId, SP_BACKGROUND);
- }
- }
- //ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
- Parcel reply;
- status_t error;
- 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) {
- // We only have a weak reference on the target object, so we must first try to
- // safely acquire a strong reference before doing anything else with it.
- if (reinterpret_cast<RefBase::weakref_type*>(
- tr.target.ptr)->attemptIncStrong(this)) {
- error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
- &reply, tr.flags);
- reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
- } else {
- error = UNKNOWN_TRANSACTION;
- }
- } else {
- error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
- }
- //ALOGI("<<<< 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);
- if (error < NO_ERROR) reply.setError(error);
- sendReply(reply, 0);
- } else {
- LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
- }
-
- mCallingPid = origPid;
- mCallingUid = origUid;
- mStrictModePolicy = origStrictModePolicy;
- mLastTransactionBinderFlags = origTransactionBinderFlags;
- 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.readPointer();
- proxy->sendObituary();
- mOut.writeInt32(BC_DEAD_BINDER_DONE);
- mOut.writePointer((uintptr_t)proxy);
- } break;
-
- case BR_CLEAR_DEATH_NOTIFICATION_DONE:
- {
- BpBinder *proxy = (BpBinder*)mIn.readPointer();
- 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)
- if (self->mProcess->mDriverFD > 0) {
- ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0);
- }
- #endif
- delete self;
- }
- }
- void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data,
- size_t /*dataSize*/,
- const binder_size_t* /*objects*/,
- size_t /*objectsSize*/, void* /*cookie*/)
- {
- //ALOGI("Freeing parcel %p", &parcel);
- IF_LOG_COMMANDS() {
- alog << "Writing BC_FREE_BUFFER for " << data << endl;
- }
- ALOG_ASSERT(data != NULL, "Called with NULL data");
- if (parcel != NULL) parcel->closeFileDescriptors();
- IPCThreadState* state = self();
- state->mOut.writeInt32(BC_FREE_BUFFER);
- state->mOut.writePointer((uintptr_t)data);
- }
- }; // namespace android
|