之前写过一篇从AIDL看Android跨进程通信 从Java层次去分析AIDL运行的原理,当时主要是为了学习Binder机制而写的,但是Binder机制比较复杂,打算过段时间单独的写一篇来分析。本篇文章分析startService的启动过程,也会涉及到使用Binder机制来进行跨进程通信,但是不会分析Binder机制的细节。不过还是强烈建议大家学习Binder机制,至少要了解Binder的基本架构,Android经常使用Binder来进行跨进程通信。
在Android中启动Service和Activity统一由ActivityManagerService(简称AMS)管理,AMS在系统启动时,就已经在ServiceManager中注册了,存活于system_server进程中。先来了解一下ActivityManagerService相关的类:
从类图可以看到这是典型的Binder机制,如果使用过AIDL的话,对IBinder,IInterface应该很熟悉。IActivityManager继承自IInterface,是用来管理Activity和Service的接口。ActivityManagerProxy从名字可以看出其是代理,并且是AMS在普通应用进程中的代理,通过它可以使用AMS的功能。ActivityManagerNative则可以看做AMS和Binder之间的中介,这样AMS就可以通过它向客户端提供服务了。
一 :从客户进程启动Service
我们还是使用从AIDL看Android跨进程通信 中的例子,从MainActivity来调用startService,一步一步分析:
1.1 ContextWrapper.java
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
这里的mBase实际是ContextImpl的实例,所以接着看
1.2 ContextImpl.java
/frameworks/base/core/java/android/app/ContextImpl.java
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
...省略...
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
} else if (cn.getPackageName().equals("!!")) {
throw new SecurityException(
"Unable to start service " + service
+ ": " + cn.getClassName());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在startServiceCommon()方法中首先验证intent是否合法,然后重点看第11~13行。想要继续跟下去就得先搞清楚ActivityManagerNative.getDefault()
是个什么鬼。
1.3 ActivityManagerNative.java
/frameworks/base/core/java/android/app/ActivityManagerNative.java
/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*/
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);
}
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
...省略...
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
第22行,将会回调Singleton的create()方法,对应28~38行代码,第29行通过ServiceManager.getService("activity")
可以获取一个IBinder,AMS在系统启动的时候已经在ServiceManager中注册过,这里我们只用知道通过这个IBinder对象(具体是BinderProxy对象)我们可以发起远程调用。通过第15行生成了一个ActivityManagerProxy并且将其作为单例保存起来,下次调用可以直接使用了。
![这里写图片描述]
上图也可以印证我们的分析。ActivityManagerNative.getDefault()
返回的是ActivityManagerProxy实例,那么1.2中将会调用ActivityManagerProxy.startService()方法。
1.4 ActivityManagerProxy.java
该类是在ActivityMangerNative中声明。
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeString(callingPackage);
data.writeInt(userId);
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
ComponentName res = ComponentName.readFromParcel(reply);
data.recycle();
reply.recycle();
return res;
}
第12行mRemote是在ActivityManagerProxy的构造方法中赋值的,还记得刚刚new ActivityManagerProxy时传入了一个IBinder(BinderProxy)吗?通过它的transact()方法像远端AMS发起请求。
二 system_server进程中AMS响应
根据Binder机制,ActivityManagerNative的onTransact()方法将会回调,因为这个方法比较长,我只截取了响应startService动作的代码。
2.1 ActivityManagerNative.java
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...省略...
case START_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
String callingPackage = data.readString();
int userId = data.readInt();
ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
reply.writeNoException();
ComponentName.writeToParcel(cn, reply);
return true;
}
...省略...
}
}
第9行,这里将要涉及到另外一个跨进程通信,主要是干什么的呢,我们知道MainActivity所在进程A通过IActivityManager接口可以调用AMS的服务,那么如果AMS想要访问进程A的服务该怎么办呢,通过这里的IApplicationThread接口可以做到。下面是相关类图:
和之前的IActivityManager类似,使用IApplicationThread也是基于Binder架构的,所以它们的结构都很像,所以这里的ApplicationThreadProxy就是A进程在AMS的一个Binder代理,通过它AMS就可以调用A进程的服务。
第14行startService()是IActivityManager接口的方法,因为ActivityManagerNative是一个抽象类,并且AMS继承了ActivityManagerNative,所以这里startService()的真正实现在ActivityManagerService中。
2.2 ActivityManagerService.java
/frameworks/base/services/core/java/com/android/server/am
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (callingPackage == null) {
throw new