• Binder机制_总纲


    前言

    Binder 从java到c++到kernel,涉及的内容很多,很难在一篇文章中说清楚。这篇主要是自我记录,方便后续查询并拆分总结的。
    因为涉及的的确非常多,不能面面俱到,所以可能一些地方感觉比较模糊、没说明白的。这需要自己去阅读了解。文章很长,需要耐心。
    关于基础部分,并不是都要了解了才行,而是要完全弄清楚Binder各个层次需要,列出的一些需要多关注的知识点。
    另外,该篇文章着重在注册服务和获取服务的过程,有详细的代码流程(这个有点复杂、占篇幅很大部分)辅助理解 注册和获取服务过程的整体思想把握。

    基础

    不做详细介绍,只是列出。
    如前言所说,基础部分并非都要全部了解才可理解Binder。只是列出的需要多关注的地方。

    进程空间

    这里的进程空间就是进程在内存中的空间。在linux中,有

    • 进程分为内核空间和用户空间。 内核空间存放内核的代码和数据,用户空间存放用户程序的代码和数据。
    • 每个进程通过系统调用进入内核空间。 进程通过系统调用进入内核运行,这时被称为内核态 。当进程执行程序自己的代码时,称为用户态
    • 所有进程共享同一个内核空间。
    • 内核空间为内核保留,一直驻存在内存中。 不允许应用读写该区域或者直接调用内核代码方法。
    • 用户空间不能直接访问硬件设备。

    Binder跨进程通信,就是借用了这个。
    示意图:
    user_kernel_space
    进程了解 可以参考下:浅谈进程&线程

    IPC基础

    需要清楚:进程是独立的,一个进程不能直接访问另一个进程。

    进程间如果需要交换数据、进行通信,这个就是IPC(进程间通信/跨进程通信)。可以参考相关文章大致了解下:
    随笔分类 - Android_系统_进程线程

    内存映射(mmap)

    这里简单将,就是将用户空间一段内存地址映射到内核空间,映射关系建立后,任一修改都能反应到另一方。

    Parcel

    一个容器对象,包含数据和对象引用,支持序列化和跨进程后的反序列化。这里主要用于binder的跨进程通信。

    AIDL

    Android Interface definition language,接口定义语言,可以了解下。

    Binder

    IPC在Android中很多:如显然四大组件都需要进行IPC。
    Andriod没有使用Linux中的各种IPC机制(进程间通信概述),通过基于OpenBinder的定制修改,实现了自己的一套轻量级的IPC机制---Binder。
    在Android中,Binder几乎用于所有核心的跨进程事件中。

    相对于Linux中其他IPC机制,那么Binder有什么优点呢?

    优点

    • Binder只需进行1次数据拷贝。
      共享内存不需数据拷贝但控制复杂;其他方式一般需要进行两次数据拷贝;Binder只需1次,通过内存映射机制进行数据传递。
    • 稳定性好。
      C/S架构,职责分明。
    • 安全。
      加入了强大的安全机制。

    Binder概述

    Binder是基于C/S模式。主要有这几个部分:

    角色 作用
    Server进程 服务端,提供服务的进程。
    Client进程 客户端,使用服务的进程。上层应用。
    ServerManager进程 管理服务。Server需要向它注册自己提供的服务。Client向它查询、获取需要的服务。
    Binder驱动 核心部分,Client通过它发送请求到Server,Server通过它返回结果到Client。内核中的驱动设备/dev/binder。

    下面详述中会具体说到。

    Binder---IPC

    首先,总体上就如上述进程空间描述。Binder通过内核进行跨进程。
    具体点,如下图:
    binder_s_c
    服务通过binder驱动注册到ServiceManager,ServiceManager保存了服务的名称、handle等信息 并加入svclist列表中。客户端通过binder驱动向ServiceManager进程查询获取到对应的服务的handle,然后binder将信息返回给客户端,客户端获取得到相应的服务Binder。

    详述Binder的流程

    下面AMS的注册和获取为例说明。Binder过程比较复杂,其中最需注意的是各个层次(java层/c++/kernel) IBinder对象具体是什么。
    Binder源码,java层和c++层在 framework/下。驱动层在 kernel/下。
    Android AOSP没有kernel源码,得单独下载。这里阅读的源码是AndroidQ的,AOSP部分是android-10.0.0_r40;kernel部分是MTK的,主要两个文件路径在kernel-4.9/drivers/android/binder.c和kernel-4.9/include/uapi/linux/android/binder.h。
    另外,下面的过程很多地方 很多方法都需要详细研究的。下面尽量简化了,即使这样(也是水平有限),内容也很长。


    主要是一个进程如何与另一个进程通信。围绕这 下面主要介绍了几点:

    • Service是如何注册的
    • ServerManager的创建,这里涉及到Service的注册和获取。
    • Client是如何获取服务的

    服务注册

    AMS注册过程概述

    服务是Context.ACTIVITY_SERVICE。

    下面是画的一个注册过程的相对完整的流程(不是类图。文章是MD的,可以直接查看文本看到图片地址,该图片地址。使用wps画的 由于非会员,图形个数有限制带了水印。),再结合代码详细说明下。
    binder_service_register
    这是一个理想的状态流程,比如实际中很多对象从保存好的地方直接获取不需重新创建。

    简述:
    注册传入了两个主要参数(服务名:activity,Binder:this)。通过一系列调用,最终将服务的名称和Binder等写入到了数据包Parcel(data)中,最终进入了Binder驱动。Binder驱动为AMS创建了binder结点binder_node。最后Binder驱动将相关信息给到ServerManager进程,ServiceManager将其封装加入svclist列表完成注册。

    注册详细过程

    系统启动后,这个服务即开始注册。这个很简单,注意传入的服务名是Context.ACTIVITY_SERVICE(即activity),以及this(AMS本身,也是继承了IBinder的Binder实体)。

    SystemServer.java:
    private void startBootstrapServices() {
        ......
        mActivityManagerService.setSystemProcess();
        ......
    }
    
    ActivityManagerService.java:
    public void setSystemProcess() {
        ......
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
        ......
    }
    
    ServiceManager.java:
    @UnsupportedAppUsage
    public static void addService(String name, IBinder service, boolean allowIsolated,
                                  int dumpPriority) {
        ......
        getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
        ......
    }
    
    

    getIServiceManager().addService(),这里需要弄清楚的就是getIServiceManager()和addService()两个方法,下面正式开始注册流程。

    getIServiceManager()

    ServiceManager.java:
    @UnsupportedAppUsage
    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
    
        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }
    

    关键的一句,这里有几个需要依次弄清楚的。

    1. BinderInternal.getContextObject()
    2. Binder.allowBlocking()
    3. ServiceManagerNative.asInterface()
    4. getIServiceManager().addService():获取的是IServiceManager,这也是个接口。需要弄清楚getIServiceManager()获取的sServiceManager实际对象是什么在来看addService()方法。
      -----回顾点1: getIServiceManager()具体是什么对象;addService()具体是什么

    详细来看下这4点:
    先看第一点(1/4)

    BinderInternal.getContextObject()

    BinderInternal.java:
    @UnsupportedAppUsage
    public static final native IBinder getContextObject();     
    
    frameworks/base/core/jni/android_util_Binder.cpp:
    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
    
    static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
    {
        sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
        return javaObjectForIBinder(env, b);
    }
    

    getContextObject()是native修饰的方法,通过jni,进入了C++。
    下面主要来看下ProcessState::self()->getContextObject(NULL)和javaObjectForIBinder(env, b)。
    -----回顾点2: getContextObject()具体获取的是什么

    先看下ProcessState::self()
    ProcessState.java:
    #ifdef __ANDROID_VNDK__
    const char* kDefaultDriver = "/dev/vndbinder";
    #else
    const char* kDefaultDriver = "/dev/binder";
    #endif
    
    #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(kDefaultDriver);
        return gProcess;
    }
    
    ProcessState::ProcessState(const char *driver)
        : mDriverName(String8(driver))
        , mDriverFD(open_driver(driver))
        ......
    {
        ......
        mVMStart = mmap(nullptr, 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);
        ......
    }
    

    从代码能够看到最终通过open_driver()方法打开了/dev/binder或者/dev/vndbinder驱动。通过ioctl进入binder内核并建立联系,在binder内核中创建了binder_proc并设置进程的最大线程数。
    注意两个个设置:

    • DEFAULT_MAX_BINDER_THREADS:这个fd最大线程数为15
    • BINDER_VM_SIZE:ProcessState初始话的内存映射大小:1G-8k(注:这个值也又不同的情况,这里不扩展)

    在接着看ProcessState::self()->getContextObject(NULL)
    sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
    {
        return getStrongProxyForHandle(0);
    }
    
    sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
    {
        sp<IBinder> result;
        ......
        handle_entry* e = lookupHandleLocked(handle);
        if (e != nullptr) {
            IBinder* b = e->binder;
            if (b == nullptr || !e->refs->attemptIncWeak(this)) {
                .......
                b = BpBinder::create(handle);
                e->binder = b;
                if (b) e->refs = b->getWeakRefs();
                result = b;
            } else {
                result.force_set(b);
                e->refs->decWeak(this);
            }
        }
        return result;
    }
    

    回到回顾点2,getContextObject()获取了句柄为0的BpBinder。先lookupHandleLocked()尝试获取,没有则创建了一个BpBinder对象。
    BpBinder的handle,如果是0 则该BpBinder是servicemanager的binder引用,如果非0 其handle值就是不同Service的hanlde 关联了各个Service。也就是说任何的系统service都可以通过BpBinder(0)就能知道servicemanager的地址。
    -----注意点1: 这个handle为0的BpBinder很重要,binder驱动等地方都有关联。

    在来看return的方法,javaObjectForIBinder(env, b):
    frameworks/base/core/jni/android_util_Binder.cpp:  
    jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
    {
        ......
        if (val->checkSubclass(&gBinderOffsets)) {
            // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
            jobject object = static_cast<JavaBBinder*>(val.get())->object();
            LOGDEATH("objectForBinder %p: it's our own %p!
    ", val.get(), object);
            return object;
        }
    
        BinderProxyNativeData* nativeData = new BinderProxyNativeData();
        nativeData->mOrgue = new DeathRecipientList;
        nativeData->mObject = val;
        jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
                gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
        ......
        return object;
    }
    

    在注册过程,返回的是BinderProxy。前面知道传入的是BpBinder对象,这是native层的对象在Java层无法使用,转换成BinderProxy。


    接着看第二点(2/4)

    Binder.allowBlocking()

    Binder.java:
    public static IBinder allowBlocking(IBinder binder) {
        try {
            if (binder instanceof BinderProxy) {
                ((BinderProxy) binder).mWarnOnBlocking = false;
            } else if (binder != null && binder.getInterfaceDescriptor() != null
                    && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {
                Log.w(TAG, "Unable to allow blocking on interface " + binder);
            }
        } catch (RemoteException ignored) {
        }
        return binder;
    }
    

    这个没什么好说的。


    再看第三点(3/4)

    ServiceManagerNative.asInterface()

    ServiceManagerNative.java:
    @UnsupportedAppUsage
    static public IServiceManager asInterface(IBinder obj)
    {
        .......
        return new ServiceManagerProxy(obj);
    }
    

    通过这个,返回了一个ServiceManagerProxy对象,并传入了BinderProxy对象。

    回到回顾点1,从上面一系列可以看出getIServiceManager().addService(name, service, allowIsolated, dumpPriority);这句话:
    getIServiceManager()获取的是ServiceManagerProxy对象,参数obj是BinderProxy。

    addService()

    接着看最后一点(4/4),addService()
    最后来看下ServiceManagerProxy中的相关方法(ServiceManagerProxy是ServiceManagerNative内部类),即getIServiceManager().addService():

    ServiceManagerNative.java:
    class ServiceManagerProxy implements IServiceManager {
        public ServiceManagerProxy(IBinder remote) {
            mRemote = remote;
        }
        
        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();
        }
    }
    

    注意data.writeStrongBinder(service);这里写入的IBinder对象是AMS最初传入的this,是Binder的实例,而不是BinderProxy。
    这里的mRemote即创建ServiceManagerProxy对象时传入的BinderProxy。


    下面就是开始进入binder驱动了,得耐心接着看了。

    先看下writeStrongBinder()

    这个写入过程稍微注意下。

    Parcel:
    public final void writeStrongBinder(IBinder val) {
        nativeWriteStrongBinder(mNativePtr, val);
    }
    private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
    
    frameworks/base/core/jni/android_os_Parcel.cpp:
    {"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
    
    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:
    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;
    }
    
    class JavaBBinderHolder
    {
    public:
        sp<JavaBBinder> get(JNIEnv* env, jobject obj)
        {
            AutoMutex _l(mLock);
            sp<JavaBBinder> b = mBinder.promote();
            if (b == NULL) {
                b = new JavaBBinder(env, obj);
           ......
    };
    
    class JavaBBinder : public BBinder
    {
        .....
    }
    

    上面已经说过,这里的service就是AMS对象,即Binder实例。所以writeStrongBinder()写入的service通过ibinderForJavaObject(env, object)封装成JavaBBinder(也即BBinder)。即服务Service对象转换成BBinder,传入到binder驱动了。

    parcel->writeStrongBinder(ibinderForJavaObject(env, object));
    -->
    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)
    {
        ......
        if (binder != nullptr) {
            BBinder *local = binder->localBinder();
            if (!local) {
                .......
            } else {
                obj.hdr.type = BINDER_TYPE_BINDER;
        .....
    

    上面看到这里binder是BBinder对象,注意这里的hdr.type = BINDER_TYPE_BINDER ,在binder驱动中有使用。

    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0)

    接着Java层从此开始向binder驱动传递

    BinderProxy:
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        ......
         try {
            return transactNative(code, data, reply, flags);
        ......
    }
    
    public native boolean transactNative(int code, Parcel data, Parcel reply,
                int flags) throws RemoteException;
           
    frameworks/base/core/jni/android_util_Binder.cpp:
    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
    
    static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
            jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
    {......
    Parcel* data = parcelForJavaObject(env, dataObj);
    Parcel* reply = parcelForJavaObject(env, replyObj);
    ......
    IBinder* target = getBPNativeData(env, obj)->mObject.get();
    ......
    status_t err = target->transact(code, *data, reply, flags);
    ......
    }
    

    parcelForJavaObject将data、reply两个Parcel由Java对象转换成C++。
    getBPNativeData()获取的是BpBinder对象。

    接下来看BpBinder中的transact()。

    frameworks/native/libs/binder/BpBinder.cpp:
    status_t BpBinder::transact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        // Once a binder has died, it will never come back to life.
        if (mAlive) {
            status_t status = IPCThreadState::self()->transact(
                mHandle, code, data, reply, flags);
        ......
    }
    
    frameworks/native/libs/binder/IPCThreadState.cpp:
    status_t IPCThreadState::transact(int32_t handle,
                                      uint32_t code, const Parcel& data,
                                      Parcel* reply, uint32_t flags)
    {
        ......
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
        err = waitForResponse(??);
        ......
    }
    
    status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
        int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
    {
        tr.target.handle = handle;
        tr.code = code;
        ......
        mOut.writeInt32(cmd);
        mOut.write(&tr, sizeof(tr));
    
        return NO_ERROR;
    }
    
    status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
    {
        ......
        while (1) {
            if ((err=talkWithDriver()) < NO_ERROR) break;
            ......
            cmd = (uint32_t)mIn.readInt32();
        .......
    }
         
    status_t IPCThreadState::talkWithDriver(bool doReceive)
    {
        ......
        do {
            ......
            if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
                err = NO_ERROR;
            else
                err = -errno;
            ......
        } while (err == -EINTR);
        ......
        if (bwr.read_consumed > 0) {
            mIn.setDataSize(bwr.read_consumed);
            mIn.setDataPosition(0);
        }
        ......
    }
    

    transact()中关键两步,writeTransactionData()和waitForResponse()。
    writeTransactionData()将要传递的数据及命令写入到mOut。这里要发送的命令是BC_TRANSACTION。 在注意的是,handle标识的是目标端,这里是0。即注册中目标是Servicemanager(handle 0 对应 binder_context_mgr_node对象)。
    waitForResponse()中while(1)死循环,通过talkWithDriver()中ioctl进入binder,这里传入到binder_ioctl的参数cmd是BINDER_WRITE_READ。
    waitForResponse()很重要,在死循环中会对binder返回的应答进行处理,cmd = (uint32_t)mIn.readInt32();获取应答的命令类型。
    另外,注意下传入transact()中的flag为0(即非TF_ONE_WAY)。

    进入binder驱动

    通过ioctl(),进入了binder内核

    {kernel}/drivers/android/binder.c
    
    static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    {
        .....
        switch (cmd) {
            case BINDER_WRITE_READ:
                ret = binder_ioctl_write_read(filp, cmd, arg, thread);
                if (ret)
                    goto err;
                break;
        ......
    }
    
    static int binder_ioctl_write_read(struct file *filp,
    				unsigned int cmd, unsigned long arg,
    				struct binder_thread *thread)
    {
        ......
        if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
    		ret = -EFAULT;
    		goto out;
    	}
        ......
        if (bwr.write_size > 0) {
    		ret = binder_thread_write(proc, thread,
    					  bwr.write_buffer,
    					  bwr.write_size,
    					  &bwr.write_consumed);
            ......
            if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
    				ret = -EFAULT;
    			goto out;
        ......
        if (bwr.read_size > 0) {
    		ret = binder_thread_read(proc, thread, bwr.read_buffer,
    					 bwr.read_size,
    					 &bwr.read_consumed,
    					 filp->f_flags & O_NONBLOCK);
        ......
    }
    
    static int binder_thread_write(struct binder_proc *proc,
    			struct binder_thread *thread,
    			binder_uintptr_t binder_buffer, size_t size,
    			binder_size_t *consumed)
    {
        ......
        void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
    	void __user *ptr = buffer + *consumed;
        ......
        if (get_user(cmd, (uint32_t __user *)ptr))
        ......
        switch (cmd) {
        ......
        case BC_TRANSACTION:
        case BC_REPLY: {
            struct binder_transaction_data tr;
    
            if (copy_from_user(&tr, ptr, sizeof(tr)))
                return -EFAULT;
            ptr += sizeof(tr);
            binder_transaction(proc, thread, &tr,
                       cmd == BC_REPLY, 0);
            break;
        }
        ......
        }
    }
    

    通过系统调用,进入binder驱动的binder_ioctl()方法,这里传入的cmd是BINDER_WRITE_READ(),上面 BpBinder中的transact()有说。
    上面 BpBinder中的transact()也说过发送命令在mOut中是BC_TRANSACTION,这时通过copy_from_user()从用户空间拷贝数据到了内核空间。最终进入到binder_transaction()事务处理。
    注意第四个参数cmd==BC_REPLY为false

    最重要的binder_transaction()

    static void binder_transaction(struct binder_proc *proc,
    			       struct binder_thread *thread,
    			       struct binder_transaction_data *tr, int reply,
    			       binder_size_t extra_buffers_size)
    {
        .....
        if(reply){
        ......
        }else {
            if (tr->target.handle) {
            ......
            } else {
                ......
                target_node = context->binder_context_mgr_node;
                ......
            }
        }
        ......
            switch (hdr->type) {
                case BINDER_TYPE_BINDER:
                case BINDER_TYPE_WEAK_BINDER: {
                    struct flat_binder_object *fp;
    
                    fp = to_flat_binder_object(hdr);
        #ifdef BINDER_WATCHDOG
                    ret = binder_translate_binder(tr, fp, t, thread);
        #else
                    ret = binder_translate_binder(fp, t, thread);
        #endif
        ......
    	tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
    	t->work.type = BINDER_WORK_TRANSACTION;
    	......
    	if (!binder_proc_transaction(t, target_proc, 
    }
    
    #ifdef BINDER_WATCHDOG
    static int binder_translate_binder(struct binder_transaction_data *tr,
    ......
    {
        struct binder_node *node;
        node = binder_get_node(proc, fp->binder);
    	if (!node) {
    		node = binder_new_node(proc, fp);
    		if (!node)
    			return -ENOMEM;
    #ifdef BINDER_WATCHDOG
    		parse_service_name(tr, proc, node->name);
    #endif
        ......
        ret = binder_inc_ref_for_node(target_proc, node,
    			fp->hdr.type == BINDER_TYPE_BINDER,
    			&thread->todo, &rdata);
        ......
    	if (fp->hdr.type == BINDER_TYPE_BINDER)
    		fp->hdr.type = BINDER_TYPE_HANDLE;
        fp->binder = 0;
    	fp->handle = rdata.desc;
    }
    
    /* this is an addService() transaction identified by:
     * fp->type == BINDER_TYPE_BINDER && tr->target.handle == 0
     */
    void parse_service_name(struct binder_transaction_data *tr,
    

    binder_transaction()这个事务处理方法很长,这里主要说下几个注意点。
    reply:前面流程传入的为false,cmd是BC_TRANSACTION。说明这是一个Client发给Server的请求事务,在Client端线程上。若为true,即是BC_REPLY说明这是一个Server发给Client的事务处理回复。在server端的线程上。
    tr->target.handle:如果是BC_TRANSACTION(这里注册中是这个),接着判断tr->target.handle。如果>0,即目标为普通Service,如果为0,则目标service是ServiceManager。从而获取目标结点target_node,进一步获取目标进程、目标线程及相关信息。
    前面有讲到传递的BBinder对象中hdr.type = BINDER_TYPE_BINDER。最终有走到binder_translate_binder,为注册服务创建了binder_node结点,保存了服务的进程及相关信息。

    向servicemanager添加BINDER_WORK_TRANSACTION事务,接下来进入ServiceManager进程。

    handle值(也待详细了解//TODO):
    binder_get_node()->binder_new_node()->binder_inc_ref_for_node()->binder_get_ref_for_node_olocked(),不详述。
    new_ref->data.desc,data.desc即handle。

    handle值计算方法规律:
    每个进程binder_proc所记录的binder_ref的handle值是从1开始递增的;
    所有进程binder_proc所记录的handle=0的binder_ref都指向service manager;
    同一个服务的binder_node在不同进程的binder_ref的handle值可以不同;

    接下来的注册过程进入ServiceManager,从下面ServiceManager的创建过程了解。

    ServiceManager的创建

    ServiceManager本身也是Binder服务,但它通过自身的binder.c与Binder驱动直接通信。通过循环binder_loop进行读取和处理事务。
    主要关注两个文件:frameworks/native/cmds/servicemanager/service_manager.cframeworks/native/cmds/servicemanager/binder.c

    系统启动通过init.rc创建并启动servicemanager。直接看其中main()方法。

    frameworks/native/cmds/servicemanager/service_manager.c:
    int main(int argc, char** argv)
    {
        ......
        //打开binder驱动,申请128k字节大小的内存空间
        bs = binder_open(driver, 128*1024);
        ......
        if (binder_become_context_manager(bs)) {
        ......
        binder_loop(bs, svcmgr_handler);
        ......
    }
    

    重点需要关注的是上述3个方法,依次来看:

    struct binder_state *binder_open(const char* driver, size_t mapsize)
    {
        ......
        bs->fd = open(driver, O_RDWR | O_CLOEXEC);
        ......
        if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
            (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
        ......
        bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
        ......
    }
    
    frameworks/native/cmds/servicemanager/binder.c:
    int binder_become_context_manager(struct binder_state *bs)
    {
        int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);
    
        // fallback to original method
        if (result != 0) {
            android_errorWriteLog(0x534e4554, "121035042");
    
            result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
        }
    }
    void binder_loop(struct binder_state *bs, binder_handler func)
    {
        ......
        readbuf[0] = BC_ENTER_LOOPER;
        binder_write(bs, readbuf, sizeof(uint32_t));
        for (;;) {
            bwr.read_size = sizeof(readbuf);
            bwr.read_consumed = 0;
            bwr.read_buffer = (uintptr_t) readbuf;
    
            res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
            ......
            res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
        ......
    }
    
    int binder_parse(struct binder_state *bs, struct binder_io *bio,
                     uintptr_t ptr, size_t size, binder_handler func)
    {
        while (ptr < end) {
            uint32_t cmd = *(uint32_t *) ptr;
            case BR_TRANSACTION_SEC_CTX:
            case BR_TRANSACTION: {
            ......
                    res = func(bs, &txn, &msg, &reply);
                    if (txn.transaction_data.flags & TF_ONE_WAY) {
                        binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
                    } else {
                        binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
                    }
         ......
    }
    
    void binder_send_reply(struct binder_state *bs,
    ......
    {
        ......
        data.cmd_reply = BC_REPLY;
        ......
        binder_write(bs, &data, sizeof(data));
    }
    

    binder_open():这个比较简单,通过系统调用在binder驱动中创建binder_proc对象,调用mmap()内存映射分配了128K的内存空间。
    binder_become_context_manager():使servicemanager成为上下文的管理者,创建了全局的binder_node对象binder_context_mgr_node。
    binder_loop();这个是最重要的方法,进入死循环,等待Client端的请求。解析binder信息,此处参数ptr指向BC_ENTER_LOOPER,func指向svcmgr_handler。故有请求到来(如BR_TRANSACTION),则调用svcmgr_handler处理,处理完成后会发送BC_REPLY。


    看看svcmgr_handler

    frameworks/native/cmds/servicemanager/service_manager.c:
    int svcmgr_handler(struct binder_state *bs,
                       struct binder_transaction_data_secctx *txn_secctx,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
    ......
        switch(txn->code) {
        case SVC_MGR_GET_SERVICE:
        case SVC_MGR_CHECK_SERVICE:
            handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
                            (const char*) txn_secctx->secctx);
            bio_put_ref(reply, handle);
        case SVC_MGR_ADD_SERVICE:
            if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
                        txn->sender_pid, (const char*) txn_secctx->secctx))
        ......
        bio_put_uint32(reply, 0);
    ......
    }
    

    SVC_MGR_ADD_SERVICE就是从addService那拆解来的。SVC_MGR_GET_SERVICE类似。
    ServiceManager最核心的两个功能为查询和注册服务:
    注册服务:do_add_service(),记录服务名和handle信息,保存到svclist列表;
    查询服务:do_find_service(),根据服务名查询相应的的handle信息。

    这样,服务就注册到ServiceManager。能够被客户端获取。

    客户端获取服务

    获取服务概述

    同服务注册一样,先看下大致的流程图。
    binder_client

    简述:
    客户端通过binder驱动从servicemanager进程查询到服务的handle,servicemanager进程同样应答binder驱动,binder驱动通过处理,向客户端返回正确的数据命令,客户端从而获取到服务的Binder对象。完成获取服务的的操作。

    获取服务详细过程

    直接来看

    ActivityManager.getService():

    ActivityManager:
    @UnsupportedAppUsage
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
    
    @UnsupportedAppUsage
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
    

    ServiceManager.getService(Context.ACTIVITY_SERVICE):

    ServiceManager:
    @UnsupportedAppUsage
    private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>();
    
    @UnsupportedAppUsage
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return Binder.allowBlocking(rawGetService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
    
    private static IBinder rawGetService(String name) throws RemoteException {
        ......
        final IBinder binder = getIServiceManager().getService(name);
        ......
    }
    

    getIServiceManager()与注册时的流程差不多,返回的是ServiceManagerProxy对象,不在依次赘述了。

    直接看下getService()

    ServiceManagerNative.java->
    class ServiceManagerProxy:
    @UnsupportedAppUsage
    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }
    

    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);进入binder驱动的也与注册类似。不多赘述。
    这里过程大致是,通过transact进入binder驱动,同样找到的目标端是servicemanager,向servicemanager发送请求(BR_TRANSACTION)查询服务(上述ServiceManager创建中),servicemanager查询服务获得服务的handle,通过BC_REPLY返回到binder驱动。binder驱动获得服务的handle,最终同样走到binder_transaction()。binder_thread_read()。

    mRemote.transact()

    下面是一些信息(do_find_service()查询到服务handle后通过bio_put_ref回应的一些信息,binder中进行处理的重要信息):

    void bio_put_ref(struct binder_io *bio, uint32_t handle)
    {
        ......
        obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
        obj->hdr.type = BINDER_TYPE_HANDLE;
        obj->handle = handle;
        obj->cookie = 0;
    }
    

    最终进入binder_transaction()

    static void binder_transaction(struct binder_proc *proc,
    ......
            case BINDER_TYPE_HANDLE:
    		case BINDER_TYPE_WEAK_HANDLE: {
    			struct flat_binder_object *fp;
    
    			fp = to_flat_binder_object(hdr);
    			ret = binder_translate_handle(fp, t, thread);   
    			.....
    			binder_alloc_copy_to_buffer(&target_proc->alloc,
    						    t->buffer, object_offset,
    						    fp, sizeof(*fp));
    }
    
    static int binder_translate_handle(struct flat_binder_object *fp,
    ......
        if (node->proc == target_proc) {
            ......
    		if (fp->hdr.type == BINDER_TYPE_HANDLE)
    			fp->hdr.type = BINDER_TYPE_BINDER;
    		else
    			fp->hdr.type = BINDER_TYPE_WEAK_BINDER;
    		fp->binder = node->ptr;
    		fp->cookie = node->cookie;
    		......
        } else {
            ......
            ret = binder_inc_ref_for_node(target_proc, node,
    				fp->hdr.type == BINDER_TYPE_HANDLE,
    				NULL, &dest_rdata);
        }
    }
    

    通过上述方法依次走下去。在binder_translate_handle()中,node->proc == target_proc,当前是在servicemanager进程的,而目标进程是请求服务所在进程,所以等于判断不成立。

    这个过程非常重要,分两种情况来说:
    当请求服务的进程与服务属于不同进程,则为请求服务所在进程创建binder_ref对象,指向服务进程中的binder_node;
    当请求服务的进程与服务属于同一进程,则不再创建新对象,只是引用计数加1,并且修改type为BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER。

    通过binder_thread_read进行一些处理。binder向客户端发送BR_REPLY。

    reply.readStrongBinder()

    sp<IBinder> Parcel::readStrongBinder() const
    {
        ALOGW("BINDER_DEBUG Parcel->readStrongBinder()");
        sp<IBinder> val;
        ......
        readNullableStrongBinder(&val);
        return val;
    }
    
    status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
    {
        ALOGW("BINDER_DEBUG Parcel->readNullableStrongBinder() val=%p", val);
        return unflatten_binder(ProcessState::self(), *this, val);
    }
    
    status_t unflatten_binder(const sp<ProcessState>& proc,
        const Parcel& in, sp<IBinder>* out)
    {
        ALOGW("BINDER_DEBUG Parcel->unflatten_binder() sp<IBinder> begin");
        const flat_binder_object* flat = in.readObject(false);
    
        if (flat) {
            switch (flat->hdr.type) {
                case BINDER_TYPE_BINDER:
                    *out = reinterpret_cast<IBinder*>(flat->cookie);
                    return finish_unflatten_binder(nullptr, *flat, in);
                case BINDER_TYPE_HANDLE:
                    *out = proc->getStrongProxyForHandle(flat->handle);
                    return finish_unflatten_binder(
                        static_cast<BpBinder*>(out->get()), *flat, in);
            }
        }
        return BAD_TYPE;
    }
    

    由上面分析知道,servicemanager传入的是BINDER_TYPE_HANDLE。请求服务与服务不在同一进程,这个值未变,仍是BINDER_TYPE_HANDLE。getStrongProxyForHandle()注册时有讲过,这里不再单独列出。这里就获取到了对应服务的BpBinder(handle)。handle是从servicemanager查到对应服务的handle。这样服务获取就完成了。


    总结下readStrongBinder():
    请求服务进程与服务进程不在同一进程(如这个服务获取),返回的是BpBinder对象。如果在同一进程,则不在创建新对象 只是引用加1,返回的是BBinder对象。


    总结下 一个完整的服务注册过程与binder交互命令大致如下图:
    add_service_cmd
    服务的注册和获取基本类似,两个过程,服务端都是ServiceManager。
    Client端(BC_TRANSACTION)--->binder驱动(BR_TRANSACTION_COMPLETE)--->Client端; binder驱动(BR_TRANSACTION)--->Service端(BC_REPLY)--->binder驱动(BR_TRANSACTION_COMPLETE)--->Service端;binder驱动(BR_REPLY)--->Client端。

  • 相关阅读:
    javaSE第十五天
    javaSE第十四天
    javaSE第十三天
    javaSE第十二天
    javaSE第十一天
    javaSE第十天
    javaSE第九天
    python011 Python3 字典
    python010 Python3 元组
    python009 Python3 列表
  • 原文地址:https://www.cnblogs.com/fanglongxiang/p/13466204.html
Copyright © 2020-2023  润新知