Binder注册与查找


在阅读Activity组件相关源码时,我们经常可以看到以下方法。我们知道,App进程调用这些方法与system_server进程通信,请求它的Ams服务。

ActivityManagerNative.getDefault().Xxx()

在system_server进程中,运行Android的一些系统服务,例如Ams服务、Wms服务。每个App进程都要和它们打交道,Activity注册、窗体管理等。进程间的通信方案主要采用Binder。Binder通信的机制比较复杂,依赖Java层、底层以及驱动层。在Java层中,系统框架将这些服务都抽象成业务接口。进程通信的两端都会实现这些接口。我们从平时常见的源码开始,一步步分析Binder的基本原理,本文主要内容是Binder的注册与查找,先看一下Java层的基础架构。


Java层Binder架构

上面代码提到的getDefault方法。

static public IActivityManager getDefault() {
    return gDefault.get();//返回IActivityManager单例
}

在ActivityManagerNative类中,定义一个IActivityManager类型的单例对象。

private static final Singleton gDefault = new Singleton() {
    protected IActivityManager create() {
        IBinder b = ServiceManager.getService("activity");
        IActivityManager am = asInterface(b);  
        return am;
    }
};

单例创建时,create方法,可以看出,首先,通过ServiceManager类获取IBinder对象。然后,调用ActivityManagerNative的asInterface方法,生成IActivityManager对象。getDefault方法,获取该IActivityManager对象。因此,文章开头所述代码,客户端App获取到IActivityManager对象,再调用它的业务方法。看一下asInterface方法。

static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    return new ActivityManagerProxy(obj);
}

该方法创建一个ActivityManagerProxy,封装IBinder,它实现IActivityManager接口。所以,客户端App使用的其实是业务代理对象。

class ActivityManagerProxy implements IActivityManager {
    public ActivityManagerProxy(IBinder remote) {
        mRemote = remote;
    }

    public IBinder asBinder() {
        return mRemote;
    }

    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        ...//打包数据
        mRemote.transact;//mRemote的方法。
    }

    public boolean finishActivity(IBinder token, int resultCode, Intent resultData, boolean finishTask)
            throws RemoteException {
        ...
        mRemote.transact;//mRemote的方法。
    }
    ...//其他业务方法
    private IBinder mRemote;
}

代理对象虽然实现了业务方法,但它不关心具体业务,只是负责打包数据,然后,调用内部封装的IBinder与真正的Binder远程通信,让你感觉到使用远端真正的服务像在本地一样。下面看一下ActivityManagerNative类。

public abstract class ActivityManagerNative extends Binder implements IActivityManager {
    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
    }
    //未实现IActivityManager业务方法。  
}  

它是一个抽象类,继承Binder类,未实现IActivityManager的业务方法,重写了Binder的onTransact方法,根据业务code,路由到子类具体的业务方法中。

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
}

ActivityManagerService是ActivityManagerNative的子类,实现具体业务方法,在system_server进程提供Ams服务。
IActivityManager是业务接口,在前面提到过,进程两端都会实现该接口,他们分别是ActivityManagerProxy类(请求端)和ActivityManagerService类(服务端)。其中,请求端内部封装IBinder,服务端继承Binder,他们之间的跨进程通信依赖Binder。
在App请求端,通过ServiceManager类,获取IBinder服务,其实它是一个BinderProxy代理对象。通信的发送和接收位置分别是请求端BinderProxy的transact方法和服务端onTransact方法。IActivityManager业务Java层的Binder通信架构图。

IActivityManager业务Java层的Binder通信架构图.jpg
图中清晰的描述了Java层Binder的通信架构。我们从前面知道,ServiceManager类,根据字符串查找Binder服务,最终,获取的是BinderProxy代理对象,下面看一下Binder服务的查找过程。


Binder服务查找

若要在App中享受system_server进程的系统服务,需要获取到一个可访问服务的BinderProxy代理和业务代理。业务代理的创建前面已经介绍过,App进程通过ServiceManager类的getService方法获取服务,所谓服务,其实就是一个BinderProxy代理,看一下getService方法。

public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            //获取BinderProxy,转换成IServiceManager。
            //然后访问业务方法getService。
            return getIServiceManager().getService(name);
          }
    } catch (RemoteException e) {
    }
    return null;
}

首先,根据字符串activity在ServiceManager缓存查找,缓存Map,保存已向sm进程查找过的IBinder对象。

private static HashMap sCache = new HashMap();

如果未查到,向sm进程查询。前提条件是,system_server进程的Ams服务启动时,已向sm进程注册。

private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }
    // Find the service manager
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

我们知道,App进程向sm进程查询,也是进程间通信,同前面介绍过的App和system_server进程通信类似,通信方案依然是Binder。该方法返回IServiceManager业务代理对象,封装BinderProxy代理。不同的是,其他服务BinderProxy代理是向sm进程查询来的,而这个BinderProxy代理来自BinderInternal类的getContextObject方法,这个问题后续再看。先看一下ServiceManagerNative的asInterface方法。

static public IServiceManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    return new ServiceManagerProxy(obj);
}

创建ServiceManagerProxy,封装BinderProxy,最后,调用业务getService方法,访问sm进程。IServiceManager业务Binder通信上层架构图。

IServiceManager业务Binder通信上层架构图.jpg
源码中查找发现,在sm进程服务端,并没有一个类似ActivityManagerService的业务实现类。在请求端,调用业务代理ServiceManagerProxy的getService方法。

public IBinder getService(String name) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);//业务参数写入Parcel
    //底层通信。
    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
    IBinder binder = reply.readStrongBinder();
    ...
    return binder;
}

业务方法code和参数打包,调用BinderProxy的transact方法进行通信,sm进程读取到查询请求时,根据服务字符串对应服务Binder,(sm进程的查询流程,以及为什么没有业务实现类,等写sm源码相关时再分析)。然后,通过Parcel的readStrongBinder方法,读取IBinder,它就是我们查找对应服务的BinderProxy。到这里,Binder服务查找就结束了,ServiceManager类的代码比较简单。再看一下服务注册,与查找类似,只是这次的发起者是system_server进程。
下面,我们看一下Parcel的readStrongBinder方法,读取底层IBinder数据,它调用nativeReadStrongBinder方法,下面是对应的JNI#方法。

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr) {
    Parcel* parcel = reinterpret_cast(nativePtr);
    if (parcel != NULL) {
        return javaObjectForIBinder(env, parcel->readStrongBinder());
    }
    return NULL;
}

首先,底层Parcel的readStrongBinder方法,获取到底层IBinder,然后,调用javaObjectForIBinder方法,创建Java层对象。

sp Parcel::readStrongBinder() const {
    sp val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}

底层Parcel的方法,它调用unflatten_binder方法,意思是解析Binder。

status_t unflatten_binder(const sp& proc,
    const Parcel& in, sp* out) {
    const flat_binder_object* flat = in.readObject(false);
    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast(out->get()), *flat, in);
        }
    }
    return BAD_TYPE;
}

第二个是当前底层Parcel对象,根据flat的type类型,如果是handle句柄,通过getStrongProxyForHandle方法解析到第三个参数out中,即底层BpBinder类。

sp ProcessState::getStrongProxyForHandle(int32_t handle) {
    sp result;
    AutoMutex _l(mLock);
    handle_entry* e = lookupHandleLocked(handle);
    if (e != NULL) {
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            .. .
            b = new BpBinder(handle); //这里创建底层BpBinder。
            e->binder = b;
            ...
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
    return result;
}

这是ProcessState的方法,创建一个BpBinder,封装handle。它就是请求进程需要的底层BpBinder,handle可以找到对应的目标进程。
获取到IBinder后,调用javaObjectForIBinder方法。

jobject javaObjectForIBinder(JNIEnv* env, const sp& val) {
    ...
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        val->incStrong((void*)javaObjectForIBinder);
        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        //关联结构体地址与BinderProxy引用
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);
        ...
    }

    return object;
}

NewObject方法,创建Java层BinderProxy对象,gBinderProxyOffsets结构体的mClass类初始化是android/os/BinderProxy,构造器mConstructor初始化init方法。设置BinderProxy的内部mObject引用底层BpBinder。
JNIEnv的SetLongField方法,BinderProxy对象的变量赋值。
JNIEnv的GetObjectField方法,获取BinderProxy对象的mSelf引用,它是BinderProxy弱引用。
JNIEnv的NewGlobal方法,获取的RefrefObject是全局引用,通过attachObject方法,将关联结构体地址与BinderProxy引用(RefrefObject),保存在底层BpBinder的mObjects中。

void BpBinder::attachObject(
    const void* objectID, void* object, void* cleanupCookie,
    object_cleanup_func func) {
    AutoMutex _l(mLock);
    mObjects.attach(objectID, object, cleanupCookie, func);
}

调用mObjects的attach方法。objectID就是结构体gBinderProxyOffsets地址。
最终,javaObjectForIBinder方法,返回一个Java层BinderProxy代理对象。我们回到前面nativeReadStrongBinder对应JNI#方法,上层Parcel读取到的IBinder就是该对象。
下面我们再看一下BinderInternal类的getContextObject方法,它返回的是访问sm进程的BinderProxy对象。对应的JNI#方法,(android_util_Binder.cpp文件定义)

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) {
    sp b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

该方法的逻辑和上面一样,获取底层BpBinder,创建Java层BinderProxy对象,看一下getContextObject方法。

sp ProcessState::getContextObject(const sp& /*caller*/) {
    return getStrongProxyForHandle(0);
}

调用getStrongProxyForHandle方法,获取底层BpBinder,这个方法前面介绍过,它的入参句柄handle是0,BpBinder目标进程就是sm服务进程,sm服务进程句柄为0

总之,从Parcel中读取Binder的过程,本质是在底层创建一个BpBinder,它可以通过句柄handle找到目标进程,创建一个上层BinderProxy对象。


Binder服务注册

system_server进程启动的系统服务,需要向sm进程注册,才可以被App进程使用,服务继承Binder类。我们先看一下服务创建过程,从SystemServer的main方法开始。

public static void main(String[] args) {
    new SystemServer().run();
}

创建一个SystemServer对象,执行它的run方法。

private void run() {
    try {
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
    } catch (Throwable ex) {
    }
    Looper.loop();
}

在该方法,这三个startXxx方法将启动多个服务,在startBootstrapServices方法中,启动我们的Ams服务。

private void startBootstrapServices() {
    //获取ActivityManagerService对象
    mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
    ...
    mActivityManagerService.setSystemProcess();
}

以上两个关键方法,第一个是SystemServiceManager的startService方法,入参是一个class类,该Class继承SystemService,startService方法将创建该类实例对象,Lifecycle是内部类,继承SystemService。创建该实例时,会初始化一个ActivityManagerService对象。其他服务也还是类似的创建方式。服务内部类,一个继承SystemService的创建该服务对象的类。SystemServiceManager就可以提供统一的方法(参数继承SystemService泛型)创建服务。

public static final class Lifecycle extends SystemService {
    private final ActivityManagerService mService;
    public Lifecycle(Context context) {
        super(context);
        mService = new ActivityManagerService(context);
    }
    @Override
    public void onStart() {
        mService.start();
    }
    public ActivityManagerService getService() {
        return mService;
    }
}

ActivityManagerService继承Binder,在Binder构造创建时,触发init初始化方法,JNI#方法,底层对应android_os_Binder_init方法。创建一个底层对象JavaBBinderHolder,设置上层Binder的mObject引用。
第二个关键方法是ActivityManagerService类setSystemProcess方法。

public void setSystemProcess() {
    try {
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
        ServiceManager.addService("meminfo", new MemBinder(this));
        ....
    } catch (NameNotFoundException e) {
    }
}

此方法中就有我们比较熟悉的内容了,ServiceManager类,addService方法,注册IActivityManager服务,this代表注册的服务是ActivityManagerService对象。
下面是ServiceManager类的addService方法。

public static void addService(String name, IBinder service) {
    try {
        getIServiceManager().addService(name, service, false);
    } catch (RemoteException e) { 
    }
}

该方法和查找服务getService方法类似,也是通过ServiceManagerProxy业务代理和BinderProxy代理和sm进程通信。ServiceManagerProxy的addService方法。

public void addService(String name, IBinder service, boolean allowIsolated)
           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);
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}

该方法中,通过Parcel的writeStrongBinder方法,将Binder服务写入底层,向sm进程注册。从查找和注册这两个方法看,他们传输的Parcel都包含Binder类型的数据存取。注册方法也是IServiceManager的业务方法,发送注册请求后,sm进程会处理注册的相关事务。(同样,等写sm源码相关时再分析)。
同Binder的查找类似,我们也看一下Parcel的writeStrongBinder方法,写入底层Binder数据,它调用nativeWriteStrongBinder方法,下面是对应的JNI#方法。

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) {
    Parcel* parcel = reinterpret_cast(nativePtr);
    if (parcel != NULL) {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        ...
    }
}

首先,ibinderForJavaObject方法,根据上层传入的Binder对象,注意,这里写入Binder,而不是BinderProxy,获取底层IBinder。

sp ibinderForJavaObject(JNIEnv* env, jobject obj) {
    //返回的是JavaBBinder指针
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }
    //获取BinderProxy代理的BpBinder引用
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return (IBinder*)
            env->GetLongField(obj, gBinderProxyOffsets.mObject);
    }
    return NULL;
}

gBinderOffsets的mClass类初始化android/os/Binder,jobject对象是上层Binder类型时,获取内部mObject引用,该引用在上层Binder对象初始化是JavaBBinderHolder指针(前面代码Binder构建时初始化的),它的get方法,获取的是JavaBBinder指针。它继承底层BBinder。返回JavaBBinder指针。
然后,调用底层Parcel的writeStrongBinder方法,将JavaBBinder写入Parcel。

status_t Parcel::writeStrongBinder(const sp& val) {
    return flatten_binder(ProcessState::self(), val, this);
}

和读取类似,写入方法调用的是flatten_binder方法。

status_t flatten_binder(const sp& /*proc*/,
    const sp& binder, Parcel* out) {
    flat_binder_object obj;
    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.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.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast(local->getWeakRefs());
            obj.cookie = reinterpret_cast(local);
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }
    return finish_flatten_binder(binder, obj, out);
}

写入的是JavaBBinder指针,根据底层IBinder的localBinder方法判断,在BBinder类,重写IBinder的localBinder方法,返回它自己本身。在BpBinder类,未重写locaBinder方法,返回空。

BBinder* BBinder::localBinder() {
    return this;
}

初始化flat_binder_object结构体,将它的cookie设置JavaBBinder指针。最后,在finish_flatten_binder方法,将flat_binder_object结构体写入输出Parcel。

inline static status_t finish_flatten_binder(
    const sp& /*binder*/, const flat_binder_object& flat, Parcel* out) {
    return out->writeObject(flat, false);
}

总之,向Parcel中写入Binder的过程,本质是将底层JavaBBinder保存在flat_binder_object结构体,然后,结构体写入底层Parcel。


总结

本文主要介绍了三个部分,Java层Binder通信架构、Binder服务查找、注册的流程,在Java层,请求进程依赖BinderProxy和业务XxxProxy,服务进程依赖Binder和业务Xxx服务。Binder通信架构不依赖业务,用户可以自己写业务接口,利用Binder机制实现进程间通信,比如aidl。
系统服务查找和注册都需要与sm进程通信。一般情况下,注册者是服务提供的system_server进程,查找者是App进程。
sm进程是Binder服务管理者,Binder服务需要向它注册才可以被使用。
ServiceManager类,框架层提供的一个服务操作类,可以通过该类提供的addService和getService方法,与sm进程通信。该类内部提供了和sm进程通信BinderProxy代理和业务代理。
与sm进程通信的BinderProxy,由BinderInternal类的getContextObject方法获取。sm进程的handle是0。
sm进程服务端,没有一个类似ActivityManagerService的业务实现类。


任重而道远

你可能感兴趣的:(Binder注册与查找)