2BinderServer

Binder Native And Java Design

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返回

NativeBBinder associated with JavaBinder

原理图

addService

frameworks/base/core/java/android/os/ServiceManager.java

ServiceManager

/**
 * 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);
}

getService && asInterface

即getiservicemanager()过程参考binderclient

useService(addService)

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();
    }
}
writeStrongBinder记录BBinder
/**
 * 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

c和javaBinder对应
    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);
}
将BBinder设置为flat_binder_object的cookie
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);
}
将flat_binder_object写入Parcel
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
}
transact(ADD_SERVICE_TRANSACTION…)
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);

serverInit

camefromzygote

frameworks/native/libs/binder/ProcessState.cpp

#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
#define DEFAULT_MAX_BINDER_THREADS 15

ProcessState::self

sp<ProcessState> ProcessState::self()
{
    gProcess = new ProcessState("/dev/binder");
    return gProcess;
}

open_driver && mmap

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;
}

startThreadPool

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

spawnPooledThread

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;
}

PoolThread::threadLoop

   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;
        }
}

IPCThreadState::joinThreadPool

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     }           

IPCThreadState::getAndExecuteCommand

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                

IPCThreadState::executeCommand

   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;

binder_transaction_data.cookie作为BBinder,调用其transact

   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     } 

JavaBBinder::onTransact调用java层Binder对应的execTransact方法

参考c和javabinder对应

    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

Threads::run

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);
    }

androidCreateRawThreadEtc

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);
}

_threadLoop

 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

IBinder

/**
 * 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

BBinder

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

IInterface

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();
};

BinderInternal_setMaxThreads

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::create

BpBinder* BpBinder::create(int32_t handle) {
    int32_t trackedUid = -1;
    if (sCountByUidEnabled) {
        trackedUid = IPCThreadState::self()->getCallingUid();
    }
    return new BpBinder(handle, trackedUid);
}