在阅读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<IActivityManager> gDefault = new Singleton<IActivityManager>() {
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通信架构图。
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<String, IBinder> sCache = new HashMap<String, IBinder>();
如果未查到,向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通信上层架构图。
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<Parcel*>(nativePtr);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
首先,底层Parcel的readStrongBinder方法,获取到底层IBinder,然后,调用javaObjectForIBinder方法,创建Java层对象。
sp<IBinder> Parcel::readStrongBinder() const {
sp<IBinder> val;
unflatten_binder(ProcessState::self(), *this, &val);
return val;
}
底层Parcel的方法,它调用unflatten_binder方法,意思是解析Binder。
status_t unflatten_binder(const sp<ProcessState>& proc,
const Parcel& in, sp<IBinder>* out) {
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat->type) {
case BINDER_TYPE_BINDER:
*out = reinterpret_cast<IBinder*>(flat->cookie);
return finish_unflatten_binder(NULL, *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;
}
第二个是当前底层Parcel对象,根据flat的type类型,如果是handle句柄,通过getStrongProxyForHandle方法解析到第三个参数out中,即底层BpBinder类。
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) {
sp<IBinder> 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<IBinder>& 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<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
该方法的逻辑和上面一样,获取底层BpBinder,创建Java层BinderProxy对象,看一下getContextObject方法。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*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<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
...
}
}
首先,ibinderForJavaObject方法,根据上层传入的Binder对象,注意,这里写入Binder,而不是BinderProxy,获取底层IBinder。
sp<IBinder> 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<IBinder>& val) {
return flatten_binder(ProcessState::self(), val, this);
}
和读取类似,写入方法调用的是flatten_binder方法。
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& 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<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(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<IBinder>& /*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的业务实现类。
任重而道远