classDiagram
class IBinder {
+queryLocalInterface(descriptor)
+linkToDeath(recipient, cookie, flags) status_t
+unlinkToDeath(recipient, cookie, flags, outRecipient) status_t
+transact(code, data, reply, flags) status_t
+localBinder() BBinder
+remoteBinder() BpBinder
}
class BpBinder {
}
class BBinder {
+transact(code, data, reply, flags)
#onTransact(code, data, reply, flags)
}
class BnInterface~INTERFACE~ {
+queryLocalInterface(_descriptor) IInterface
+getInterfaceDescriptor() descriptor
#onAsBinder() IBinder
}
class BnGraphicBufferProducer {
+onTransact() status_t
}
class IInterface {
+asBinder(IInterface*) IBinder
}
class IGraphicBufferProducer {
+ipcMethod()
}
class BufferQueueProducer {
+ipcMethod()
}
class JavaBBinder {
+onTransact()
}
IBinder <|-- BpBinder
IBinder <|-- BBinder
BBinder <|-- BnInterface : native type server
BBinder <|-- JavaBBinder : java type server
BnInterface <|-- BnGraphicBufferProducer : BnInterface<IGraphicBufferProducer>
IInterface <|-- IGraphicBufferProducer
BnGraphicBufferProducer <|-- BufferQueueProducer
IGraphicBufferProducer <|.. BnInterface : INTERFACE
classDiagram
class IBinder {
+queryLocalInterface(descriptor) IInterface
+linkToDeath(recipient, flags)
+unlinkToDeath(recipient, flags)
+transact(code, data, reply, flags)
}
class BinderProxy {
}
class Binder {
+attachInterface(iinterface, descriptor)
+transact(code, data, reply, flags)
#onTransact(code, data, reply, flags)
}
class Stub {
+asInterface(iBinder) IConnectivityManager
+asBinder() IBinder
+onTransact(code, data, reply, flags)
}
class IInterface {
+asBinder() IBinder
}
class IConnectivityManager {
+ipcMethod()
}
class ConnectivityService {
+ipcMethod()
}
class Proxy {
- IBinder mRemote
+ipcMethod()
}
IBinder <|-- BinderProxy
IBinder <|-- Binder
Binder <|-- Stub
IConnectivityManager <|.. Stub
IInterface <|-- IConnectivityManager
Stub <|-- ConnectivityService
IConnectivityManager <|.. Proxy
Stub --> Proxy : asInterface返回
frameworks/base/core/java/android/os/ServiceManager.java
/**
* Place a new @a service called @a name into the service
* manager.
*
* @param name the name of the new service
* @param service the service object
* @param allowIsolated set to true to allow isolated sandboxed processes
* @param dumpPriority supported dump priority levels as a bitmask
* to access this service
*/
public static void addService(String name, IBinder service, boolean allowIsolated,
int dumpPriority) {
getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
}
即getiservicemanager()过程参考binderclient
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
public IBinder asBinder() {
return mRemote;
}
public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
data.writeInt(dumpPriority);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
}
/**
* Write an object into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
frameworks/base/core/jni/android_os_Parcel.cpp
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
frameworks/base/core/jni/android_util_Binder.cpp
gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
// Instance of Binder?
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
return jbh->get(env, obj);
}
// Instance of BinderProxy?
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return getBPNativeData(env, obj)->mObject;
}
ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
return NULL;
}
frameworks/base/core/jni/android_util_Binder.cpp
class JavaBBinderHolder
{
public:
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
sp<JavaBBinder> b = mBinder.promote();
if (b == NULL) {
b = new JavaBBinder(env, obj);
mBinder = b;
}
return b;
}
wp<JavaBBinder> mBinder;
}
frameworks/native/libs/binder/Parcel.cpp
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
if (binder != NULL) {
IBinder *local = binder->localBinder();//本地Binder即BBinder,即Server端的Binder
if (!local) {//BBinder为空时
BpBinder *proxy = binder->remoteBinder();
const int32_t handle = proxy ? proxy->handle() : 0;
obj.hdr.type = BINDER_TYPE_HANDLE;
obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = 0;
} else { //进入该分支
obj.hdr.type = BINDER_TYPE_BINDER;//后续在binder_transaction时会被调整为BINDER_TYPE_HANDLE类型,进而保存到serviceManager的链表当中
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);//BBinder设置为flat_binder_object的cookie
}
} else {
obj.hdr.type = BINDER_TYPE_BINDER;
obj.binder = 0;
obj.cookie = 0;
}
return finish_flatten_binder(binder, obj, out);
}
inline static status_t finish_flatten_binder(
const sp<IBinder>& , const flat_binder_object& flat, Parcel* out)
{
return out->writeObject(flat, false);//将flat_binder_object写入out
}
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
frameworks/native/libs/binder/ProcessState.cpp
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
#define DEFAULT_MAX_BINDER_THREADS 15
sp<ProcessState> ProcessState::self()
{
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))//call open_driver
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// 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);
}
}
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
void ProcessState::spawnPooledThread(bool isMain)//创建一个Thread用于提供Binder服务
{
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());
}
}
String8 ProcessState::makeBinderThreadName() {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
pid_t pid = getpid();
String8 name;
name.appendFormat("Binder:%d_%X", pid, s);
return name;
}
│50 class PoolThread : public Thread
│51 {
58 protected:
│59 virtual bool threadLoop()
│60 {
>│61 IPCThreadState::self()->joinThreadPool(mIsMain);
│62 return false;
│63 }
66 };
void IPCThreadState::threadDestructor(void *st)
{
IPCThreadState* const self = static_cast<IPCThreadState*>(st);
if (self) {
self->flushCommands();
if (self->mProcess->mDriverFD > 0) {
ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0);
}
delete self;
}
}
528 void IPCThreadState::joinThreadPool(bool isMain)
│529 {
│532 mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
│533
│534 status_t result;
│535 do {
│536 processPendingDerefs();
│537 // now get the next command to be processed, waiting if necessary
>│538 result = getAndExecuteCommand();
│539
│540 if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
│541 ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
│542 mProcess->mDriverFD, result);
│543 abort();
│544 }
│545
│546 // Let this thread exit the thread pool if it is no longer
│547 // needed and it is not the main process thread.
│548 if(result == TIMED_OUT && !isMain) {
│549 break;
│550 }
│551 } while (result != -ECONNREFUSED && result != -EBADF);
│552
│556 mOut.writeInt32(BC_EXIT_LOOPER);
│557 talkWithDriver(false);
│558 }
│435 status_t IPCThreadState::getAndExecuteCommand()
│436 {
│437 status_t result;
│438 int32_t cmd;
│439
│440 result = talkWithDriver();
441 if (result >= NO_ERROR) {
│442 size_t IN = mIn.dataAvail();
│443 if (IN < sizeof(int32_t)) return result;
│444 cmd = mIn.readInt32();
>│458 result = executeCommand(cmd);
│459
│460 pthread_mutex_lock(&mProcess->mThreadCountLock);
│461 mProcess->mExecutingThreadsCount--;
│471 pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
│472 pthread_mutex_unlock(&mProcess->mThreadCountLock);
│473 }
│474
│475 return result;
│476 }
│477
│998 status_t IPCThreadState::executeCommand(int32_t cmd)
│999 {
│1000 BBinder* obj;
│1001 RefBase::weakref_type* refs;
│1002 status_t result = NO_ERROR;
│1003
│1004 switch ((uint32_t)cmd) {
1077 case BR_TRANSACTION:
│1078 {
│1079 binder_transaction_data tr;
│1080 result = mIn.read(&tr, sizeof(tr));
│1103 Parcel reply;
│1104 status_t error;
│1116 if (tr.target.ptr) {
│1117 // We only have a weak reference on the target object, so we must first try to
│1118 // safely acquire a strong reference before doing anything else with it.
│1119 if (reinterpret_cast<RefBase::weakref_type*>(
│1120 tr.target.ptr)->attemptIncStrong(this)) {
>│1121 error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
│1122 &reply, tr.flags);
│1123 reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
│1124 } else {
│1125 error = UNKNOWN_TRANSACTION;
│1126 }
│1127
│1128 } else {
│1129 error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
│1130 }
│1135 if ((tr.flags & TF_ONE_WAY) == 0) {
│1136 LOG_ONEWAY("Sending reply to %d!", mCallingPid);
│1137 if (error < NO_ERROR) reply.setError(error);
│1138 sendReply(reply, 0);
│1139 } else {
│1140 LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
│1141 }
│1155 break;
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
break;
│118 status_t BBinder::transact(
│119 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
│120 {
│121 data.setDataPosition(0);
│122
│123 status_t err = NO_ERROR;
│124 switch (code) {
│125 case PING_TRANSACTION:
│126 reply->writeInt32(pingBinder());
│127 break;
│128 default:
>│129 err = onTransact(code, data, reply, flags);
│130 break;
│131 }
│132
│133 if (reply != NULL) {
│134 reply->setDataPosition(0);
│135 }
│136
│137 return err;
│138 }
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
JNIEnv* env = javavm_to_jnienv(mVM);
//printf("Transact from %p to Java code sending: ", this);
//data.print();
//printf("\n");
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
Binder.java
// Entry point from android_util_Binder.cpp's onTransact
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
res = onTransact(code, data, reply, flags);
}
system/core/libutils/Threads.cpp
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
void *userData,
const char* threadName __android_unused,
int32_t threadPriority,
size_t threadStackSize,
android_thread_id_t *threadId)
{
int result = pthread_create(&thread, &attr,
(android_pthread_entry)entryFunction, userData);
}
│711 int Thread::_threadLoop(void* user)
│712 {
726 do {
│727 bool result;
│728 if (first) {
│729 first = false;
│730 self->mStatus = self->readyToRun();
│731 result = (self->mStatus == NO_ERROR);
│732
│733 if (result && !self->exitPending()) {
│734 // Binder threads (and maybe others) rely on threadLoop
│735 // running at least once after a successful ::readyToRun()
│736 // (unless, of course, the thread has already been asked to exit
│737 // at that point).
│738 // This is because threads are essentially used like this:
│739 // (new ThreadSubclass())->run();
│740 // The caller therefore does not retain a strong reference to
│741 // the thread and the thread would simply disappear after the
│742 // successful ::readyToRun() call instead of entering the
│743 // threadLoop at least once.
>│744 result = self->threadLoop();
│745 }
│746 } else {
│747 result = self->threadLoop();
│748 }
766 // Release our strong reference, to let a chance to the thread
│767 // to die a peaceful death.
│768 strong.clear();
│769 // And immediately, re-acquire a strong reference for the next loop
│770 strong = weak.promote();
│771 } while(strong != 0);
frameworks/native/libs/binder/include/binder/IBinder.h
/**
* Base class and low-level protocol for a remotable object.
* You can derive from this class to create an object for which other
* processes can hold references to it. Communication between processes
* (method calls, property get and set) is down through a low-level
* protocol implemented on top of the transact() API.
*/
class IBinder : public virtual RefBase
{
/**
* Check if this IBinder implements the interface named by
* @a descriptor. If it does, the base pointer to it is returned,
* which you can safely static_cast<> to the concrete C++ interface.
*/
virtual sp<IInterface> queryLocalInterface(const String16& descriptor);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0) = 0;
/**
* Register the @a recipient for a notification if this binder
* goes away. If this binder object unexpectedly goes away
* (typically because its hosting process has been killed),
* then DeathRecipient::binderDied() will be called with a reference
* to this.
*
* The @a cookie is optional -- if non-NULL, it should be a
* memory address that you own (that is, you know it is unique).
*
* @note You will only receive death notifications for remote binders,
* as local binders by definition can't die without you dying as well.
* Trying to use this function on a local binder will result in an
* INVALID_OPERATION code being returned and nothing happening.
*
* @note This link always holds a weak reference to its recipient.
*
* @note You will only receive a weak reference to the dead
* binder. You should not try to promote this to a strong reference.
* (Nor should you need to, as there is nothing useful you can
* directly do with it now that it has passed on.)
*/
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0) = 0;
frameworks/native/libs/binder/include/binder/Binder.h
class BBinder : public IBinder
{
public:
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0);
protected:
virtual ~BBinder();
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
frameworks/native/libs/binder/include/binder/IInterface.h
class IInterface : public virtual RefBase
{
public:
IInterface();
static sp<IBinder> asBinder(const IInterface*);
static sp<IBinder> asBinder(const sp<IInterface>&);
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
};
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
explicit BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
frameworks/base/core/jni/android_util_Binder.cpp
static void android_os_BinderInternal_setMaxThreads(JNIEnv* env,
jobject clazz, jint maxThreads)// called by SystemServer.java BinderInternal.setMaxThreads
{
ProcessState::self()->setThreadPoolMaxThreadCount(maxThreads);
}
frameworks/native/libs/binder/BpBinder.cpp
BpBinder* BpBinder::create(int32_t handle) {
int32_t trackedUid = -1;
if (sCountByUidEnabled) {
trackedUid = IPCThreadState::self()->getCallingUid();
}
return new BpBinder(handle, trackedUid);
}