Service是Android四大组件之一,与Activity的可视化界面相反,Service没有向用户提供交互界面,因此常被用于执行后台任务。Service的启动方式有两种:
普通启动
和绑定启动
,其中,前者通过Context.startService方法启动,常用于执行普通的后台任务;后者通过Context.bindService方法启动,用于执行与启动组件有数据交互的后台任务。本文将从Android6.0源码角度,重点阐述这两种方式的具体启动过程。
在Android应用开发中,通常普通启动一个Service是调用Context的startService()方法实现的,Context
描述一个应用程序环境的信息(即上下文),通过它我们可以获取应用程序的资源和类(包括应用级别操作,如启动Activity,发广播,接受Intent等)。Context是一个抽象类,它的具体实现类是ContextImpl,因此当我们调用Context的startService方法普通启动Service时,实际执行的是ContextImpl的startService方法。在ContextImpl的startService()
方法中,该方法会直接调用ContextImpl的startServiceCommon()
方法执行接下来的调用逻辑,其源码如下:
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess();
// ActivityManagerNative.getDefault()即AMS
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 new RuntimeException("Failure from system", e);
}
}
从startServiceCommon()方法源码可知,它主要完成两部分任务:(1) 调用ActivityManagerNative.getDefault()的startService()方法执行具体的启动过程,并返回一个ComponentName的对象cn;(2) 如果(1)执行完毕后返回的cn不为空,就判断启动service是否具有执行权限等情况。其中,ActivityManagerNative.getDefault()
返回一个IActivityManager
,它继承于接口android.os.IInterface,这个接口就厉害了,还记得在我的另一篇文章《Android源码解析之浅析Binder工作原理》中有提到过,IIterface接口通常出现在Binder通信机制中,它表明在IPC通信过程中远程Server能够提供什么样的能力或称Client与Server之间的契约,Server端的Binder本地对象和Client端的Binder代理对象均需要继承该接口。也就是说,关于service的启动,很可能是一次跨进程通信。当然,现在下结论还有点早,我们还需要把Binder本地对象和Binder代理对象找出来。果然,ActivityManagerNative
就是那个Server端的Binder实体,因为它同时继承了IBinder和IIterface。同时,我们也在ActivityManagerNative源码中找到了一个内部类ActivityManagerProxy
,从名字我们就能够猜测到它就是那个Binder的代理对象,何况它继承了IInterface。这就验证了:Service的启动实质是一次基于Binder机制的远程跨进程通信,即最终的Service启动工作是交给系统进程中的服务ActivityManagerService(简称"AMS")来完成。
为什么是ActivityManagerService?从gDefault对象的定义来看,它是一个单例对象,当该对象的get()方法被调用时,Singleton的create()方法会被调用,具体工作为:首先,调用ServiceManager的getService()获得名为"activity"的远程服务Binder实体引用,通过跟踪与ServiceManager相关源码,我们可以知道其实这一步也是一次远程IPC,而ServiceManager只是一个用于管理这些Service的管理器;然后,调用ActivityManagerNative的asInterface()方法返回一个ActivityManagerProxy对象给应用进程,之所以一定返回该代理对象,是因为我们的应用进程与系统进程不可能是同一个进程。getDefault()相关源码如下:
// 位于ActivityManagerNative.java
static public IActivityManager getDefault() {
// 返回ActivityManagerSevice实例
return gDefault.get();
}
// 位于ActivityManagerNative.java
// 单例模式
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
// Binder本地实体的引用
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
// 返回Binder代理对象ActivityManagerProxy
// 因为我们的应用不可能与系统进程归属于同一个进程
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
// 位于ActivityManagerNative.java
// 将Binder对象转换为IActivityManager
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
// 返回Binder本地对象,但这里in应该恒为null
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
// 返回Binder代理对象
return new ActivityManagerProxy(obj);
}
也就是说,gDefault.get()=ActivityManagerProxy?此言差矣!我们知道,ActivityManagerProxy中的方法,比如startService,它只是对调用参数进行了封装,真正的实现是交给远程服务的Binder实体(本地对象)完成,这个Binder实体就是ActivityManagerNative,但是ActivityManagerNative又是个抽象类,像startService这些方法均是抽象方法,ActivityManagerService才是它的实现类。因此,我们可以得出:gDefault.get()=ActivityManagerService
!
// 位于ActivityManagerProxy
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
// 封装函数参数到Parcel类型的data对象,
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeString(callingPackage);
data.writeInt(userId);
// 通过远程Binder实体的引用,调用Binder请求处理方法并将处理结果返回写入reply
// 这步由内核中的Binder驱动控制,最终调用远程Binder实体中的onTransact,
// 该方法会通过分析传入的函数code(编号)决定调用哪个方法
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
ComponentName res = ComponentName.readFromParcel(reply);
data.recycle();
reply.recycle();
return res;
}
// 位于ActivityManagerNative
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...
// 响应远程请求start Service
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();
// 调用ActivityManagerService完成Service的启动工作
ComponentName cn = startService(app, service, resolvedType,
callingPackage, userId);
reply.writeNoException();
ComponentName.writeToParcel(cn, reply);
return true;
}
...
}
小结1:
ActivityManagerService
,Service启动过程实质是一次基于Binder机制的远程跨进程通信,最终的启动工作由系统进程中的ActivityManagerService服务完成。接下来,我们就着重分析下ActivityManagerService的startService是如何启动Service,它的源码如下:
// ActivityManagerService.startService()
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {
...
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
// 调用ActiveServices的startServiceLocked方法
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
从上述源码来看,ActivityManagerService的startService()并没有执行具体的功能,而是直接调用了ActiveServices的startServiceLocked()
方法,该方法首先会获得一个ServiceRecord对象,ServiceRecord用于描述一个Service记录,它缓存了与Service有关的变量,并且会一直贯穿整个Service的启动过程;然后将该ServiceRecord对象和Intent类型的service对象作为参数调用ActiveServices的startServiceInnerLocked()
方法,该方法继续调用ActiveServices的bringUpServiceLocked()
方法,在这个方法中,我们最终会看到它会调用一个名为realStartServiceLocked
的方法,从名字可以猜测得到从这个方法开始就是真正进入启动过程了,我们来看看这个方法的源码:
// ActiveServices.realStartServiceLocked()
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
// (1) 判断应用进程是否存在,如果为null,抛出异常
if (app.thread == null) {
throw new RemoteException();
}
...
boolean created = false;
try {
...
// 执行ApplicationThread.scheduleCreateService
// 将执行逻辑从系统进程切换到应用进程,即由“内核态”切换到“用户态”
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
// 设置启动标志created为true
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
if (!created) {
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
// Cleanup.
if (newService) {
app.services.remove(r);
r.app = null;
}
// Retry.
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
// If the service is in the started state, and there are no
// pending arguments, then fake up one so its onStartCommand() will
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null));
}
// (2)当Service的onCreate方法被调用后
// 该方法最终会调用Service的onStartCommand()方法
sendServiceArgsLocked(r, execInFg, true);
...
}
该方法主要做两件事情:
(1) 通过app.thread
返回的对象判断当前应用进程是否存在,如果存在(app.thread!=null),则调用返回对象的scheduleCreateService()
方法执行接下来的启动工作,否则,抛出"RemoteException"异常。那么,app.thread返回的对象是什么呢?通过跟踪源码发现,app.thread返回一个IApplicationThread对象,但是IApplicationThread是一个接口且继承系统接口android.os.IInterface,并且ApplicationThreadNative、ApplicationThreadProxy均继承于该接口。由之前对AMS IPC的分析,我们很容易可以猜测得到app.thread.scheduleCreateService()又是一次远程跨进程调用,并且ApplicationThread、ApplicationThreadProxy分别是“服务端”的Binder本地对象和"客户端"的Binder代理对象。但是,与AMS IPC相反的是,这次的"客户端"的角色由系统进程AMS“扮演”,而"服务端"角色换成了应用进程,ApplicationThreadProxy对象就是ApplicationThread在AMS中的代理,AMS将通过该代理对象与ApplicationThread进行通信。也就是说,service的最终具体启动工作还是在应用进程中完成的,且app.thread=ApplicationThread
。ApplicationThreadNative、ApplicationThreadProxy等类关系如下:
// “契约”接口
public interface IApplicationThread extends IInterface{}
// 服务端Binder本地对象
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread {
...
// 客户端Binder代理对象
class ApplicationThreadProxy implements IApplicationThread {}
}
// 主线程管理器
public final class ActivityThread {
final H mH = new H();
...
// ApplicationThreadNative实现类,提供真正的服务实现(Binder本地对象)
private class ApplicationThread extends ApplicationThreadNative {
}
}
接下来,我们重点分析下应用进程是如何完成Service的启动工作。首先,对于ApplicationThread的scheduleCreateService()方法来说,它是运行在"服务端"的Binder线程池的线程中(原因参考本文),但是该方法并没有执行具体的启动工作,而是调用sendMessage()方法向mH发送一个H.CREATE_SERVICE
消息,通过查看源码可知,sendMessage()方法和mH对象均属于ActivitiyThread
,并且mH是一个Handler!由源码注释我们可以了解到,ActivitiyThread是一个在应用进程中用于管理主线程(main thread)的运行,比如管理和运行activities、broadcasts或者在activity执行的一些操作,从某些程度来说,ActivitiyThread就是我们熟悉的主线程或称UI线程
,它是APP的真正入口。当开启APP后,系统会调用APP的main()开始运行,此时ActivityThread就会被创建,并且在主线程中开启一个消息循环队列,而mH对象(Handler)就是这个消息循环队列的“操作手”,用来接收和处理那些传递到主线程的所有消息,其中,处理消息工作由mH.handleMessage()
完成,它将根据消息编号(H.CREATE_SERVICE)执行最终的处理业务。对于CREATE_SERVICE消息,即启动service的任务,handleMessage最终交给ActivityThread的handleCreateService()
方法来完成。
// ApplicationThread.scheduleCreateService()
// 运行在Binder线程池
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
// 发送消息
sendMessage(H.CREATE_SERVICE, s);
}
// ActivityThread.sendMessage()
// 主线程
public final class ActivityThread {
// 主线程的Handler
final H mH = new H();
...
// 实现子线程向主线程发送消息
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
// 向mH发送一个msg消息
mH.sendMessage(msg);
}
private class H extends Handler {
public static final int CREATE_SERVICE = 114;
...
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
...
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"serviceCreate");
// 处理Service创建工作
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
}
最后,我们看下ActivityThread.handleCreateService()
方法为了完成Service的启动,做了哪些工作:
(a) 创建类加载器,通过该加载器创建要启动的Service对象;
(b) 创建Application对象并调用其onCreate方法,并且在应用被启动后Application始终只会被创建一次;
// LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
// 如果mApplication被创建,则直接返回
if (mApplication != null) {
return mApplication;
}
Application app = null;
try {
java.lang.ClassLoader cl = getClassLoader();
...
ContextImpl appContext =
ContextImpl.createAppContext(mActivityThread, this);
// 创建Application
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if(instrumentation != null) {
// 调用Application的onCreate方法
instrumentation.callApplicationOnCreate(app);
}
© 创建ContextImpl对象,并通过Service的attach方法建立两者之间的关系,这个过程与Activity的启动相似;
(d) 调用Service的onCreate()方法,同时将Service对象插入到mService列表中。至此,随着onCreate()方法被调用,Service成功被启动,并且onCreate()运行在应用进程的主线程,所以尽量不要在该方法中执行耗时任务,否则,会出现ANR异常。
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
handleCreateService()源码:
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
// (1) 创建类加载器
java.lang.ClassLoader cl = packageInfo.getClassLoader();
// 加载名为name的Service类,即实例化Service
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
// (3)创建APP的ContextImpl
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
// (2) 创建Application
Application app = packageInfo.makeApplication(false, mInstrumentation);
// 将Context与Service绑定
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
// (4) 调用Service的onCreate(),即Service启动成功
service.onCreate();
// 将Service对象插入到列表中缓存
mServices.put(data.token, service);
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
// nothing to do.
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
(2) 在(1)执行完毕后,Service的onCreate()方法被调用,就说明Service已经被启动了。但我们知道,当Serivce启动后除了它的onCreate()方法被调用,还有另外一个方法也会被调用,即onStartCommand
,接下来,我们就分析下onStartCommand方法是如何被调用的。首先,我们回到ActiveServices.realStartServiceLocked()中找到sendServiceArgsLocked(r, execInFg, true)
,该方法会从SerivceRecord中取出ApplicationThread对象,然后调用该对象中的scheduleServiceArgs()
方法向主线程ActivityThread发送一个H.SERVICE_ARGS
消息。当主线程接收到该消息后,就会执行ActivityThread.handleServiceArgs()
,,然后再该方法中Service的onStartCommand方法就会被调用。具体的调用流程:
// ActiveServices.sendServiceArgsLocked()
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
...
// 调用ApplicationThread的scheduleServiceArgs
r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
...
}
// ActivityThread.ApplicationThread.scheduleServiceArgs()
// 运行在Binder线程池的线程中
public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
int flags ,Intent args) {
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = taskRemoved;
s.startId = startId;
s.flags = flags;
s.args = args;
// 向主线程发送一个H.SERVICE_ARGS消息
sendMessage(H.SERVICE_ARGS, s);
}
// ActivityThread.handleServiceArgs()
// 运行在主线程中
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
data.args.prepareToEnterProcess();
}
int res;
if (!data.taskRemoved) {
// 调用Service的onStartCommand()方法
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
// nothing to do.
}
ensureJitEnabled();
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to start service " + s
+ " with " + data.args + ": " + e.toString(), e);
}
}
}
}
小结2:
ActivityManagerService
是运行在系统进程的服务,负责系统中所有Activity、Service等组件的生命周期;ActivityThread
是App的真正入口,即传说中的主线程或称UI线程,它将与ActivityManagerService配合,实现对Activity、Service等组件的管理;ApplicationThread
是ActivityManagerService(系统服务)与ActivityThread(主线程)交互的桥梁,当ActivityManagerService需要管理Application(应用进程)中的Activity或Service等组件的生命周期时,会通过ApplicationThread的代理对象ApplicationThreadProxy与ActivityThread进行通信,然后告知ActivityThread需要执行什么操作。 绑定启动Service的实现过程与普通启动Service的流程是大致相同的,都是借助基于Binder机制的IPC方式与AMS交互实现的,只是绑定启动调用的是Context.bindService()
方法,由前面的分析可知,这步的操作实际上是执行了ContextImpl的bindService()方法。bindService方法并没有执行具体的业务逻辑,而是将工作交给了ContextImpl.bindServiceCommon()
方法,它的源码下:
// ContextImpl
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}
// ContextImpl
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
// (1) 将客户端的ServiceConnection转化为ServiceDispatcher.InnerConnction对象
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess();
// (2) 调用AMS的binderService方法
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
}
bindServiceCommon源码分析:
(1) 首先,bindServiceCommon调用LoadedApk.getServiceDispatcher()
方法获得IServiceConnection
对象sd,该方法接受一个ServiceConnection对象conn作为参数,并创建一个key、value分别为ServiceConnection和LoadedApk.ServiceDispatcher的map集合,也就是说,ServiceConnction与LoadedApk.ServiceDispatcher是一个映射关系。然后,判断集合map是否为null,如果不为null,则从集合中取出与ServiceConnection对象相关联的LoadedApk.ServiceDispatcher
对象。当然,如果map集合中不存在对象sd,则new一个ServiceDispatcher对象,并将其与ServiceConnection对象c作为一条key-value记录插入到map集合中缓存。源码如下:
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map =
mServices.get(context);
// 从map集合中取出 LoadedApk.ServiceDispatcher缓存
if (map != null) {
sd = map.get(c);
}
// 如果sd不存在map集合中,创建它
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
// 存储一个应用当前活动的ServiceConnection
// 与LoadedApk.ServiceDispatcher的映射关系
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
but,搞了半天又是IServiceConnection、又是ServiceDispatcher的到底要干嘛?实际上,考虑到bindService可能是跨进程的,而ServiceConnect对象运行在客户端,为了让自己的方法(即onServiceDisconnected
和onServiceConnected
)能够正常被远程服务端回调,ServiceConnect对象就必须借助Binder机制来实现。它的实现原理是将客户端的ServiceConnection对象转换化为ServiceDispatcher.InnerConnection对象,并且ServiceDispatcher是衔接ServiceConnection和InnerConnection的桥梁,而InnerConnection恰好可以充当Binder本地对象的角色。
LoadedApk.ServiceDispatcher相关源码如下:
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final ServiceConnection mConnection;
...
// 构造方法
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
// 运行在远程服务端的Binder实体或称Binder本地对象
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
// 缓存当前的LoadedApk.ServiceDispatcher对象
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
// 远程方法,执行调用客户端ServiceConnect对象的回调方法
public void connected(ComponentName name, IBinder service) throws
RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
// 调用LoadedApk.ServiceDispatcher的connected方法
// 该方法最终会调用ServiceConnect的回调方法
if (sd != null) {
sd.connected(name, service);
}
}
}
}
(2) 在(1)获得与ServiceConnect对应的LoadedApk.ServiceDispatcher对象后,bindServiceCommon接着将该对象作为参数继续调用ActivityManagerService(即app.thread,简称AMS)的bindService()
方法,将业务逻辑切换由应用进程到系统进程的AMS服务中。在AMS的bindService方法中,直接调用ActiveServices的bindServiceLocked()
方法,bindServiceLocked方法再调用bringUpServiceLocked
,bringUpServiceLocked又会调用realStartServiceLocked
。realStartServiceLocked的执行逻辑与普通启动Service一致,最终都是通过ApplicationThread来完成Service对象的创建并执行其onCreate方法,这里不再重复分析。realStartServiceLocked源码如下:
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
...
boolean created = false;
try {
...
// startService:调用onCreate
app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
...
}
// 调用app.thread.scheduleBindService
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
// If the service is in the started state, and there are no
// pending arguments, then fake up one so its onStartCommand() will
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null));
}
// 启动onStartCommand方法
sendServiceArgsLocked(r, execInFg, true);
...
}
与普通启动Service不同的是,绑定启动Service不仅会执行app.thread.scheduleCreateService,还会执行app.thread.scheduleBindService
,这个从跟踪requestServiceBindingsLocked
代码可以确定。接着,我们就来看ApplicationThread(即app.thread)的scheduleBindService的方法,scheduleBindService会向主线程ActivityThread发送一个H.BIND_SERVICE
消息,ActivitiyThread的H(Handler对象)接收到该消息后,就会调用ActivityThread的handleBindService
方法,源码如下:
private void handleBindService(BindServiceData data) {
// 获取对应的Service对象
Service s = mServices.get(data.token);
if (DEBUG_SERVICE)
Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
// 调用Service的onBind方法
// 返回远程Service中Binder本地对象的引用
IBinder binder = s.onBind(data.intent);
// 调用AMS的publicService方法
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
// 调用Service的onBind方法
s.onRebind(data.intent);
// 调用AMS的serviceDoneExecuting方法
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
在ActivityThread的handleBindService方法中,它首先会判断Service是否已经被绑定启动,如果data.rebind不为空,说明Service已经被绑定启动,这是会调用Service的onRebind
方法,就不会再调用Service的onBind
方法,否则,调用Service的onBind方法,然后调用AMS的publishService
方法进入绑定启动Service逻辑。publishService方法会调用ActiveServices的publishServiceLocked
方法,在该方法最终会调用LoadedApk.ServiceDispatcher.InnerConnection内部类的connected
方法,在connected实现回调客户端的ServiceConnection的方法,相关源码如下:
// ActiveServices.publishServiceLocked()方法
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
...
ConnectionRecord c = clist.get(i);
try {
// 调用ServiceDispatcher.InnerConnection的connected方法
// 实现回调客户端ServiceConnection的方法
c.conn.connected(r.name, service);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.name +
" to connection " + c.conn.asBinder() +
" (in " + c.binding.client.processName + ")", e);
}
}
// LoadedApk.ServiceDispatcher.InnerConnection内部类
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
// 调用LoadedApk.ServiceDispatcher的connected方法
sd.connected(name, service);
}
}
}
从LoadedApk.ServiceDispatcher.InnerConnection内部类的connected方法可知,它会调用LoadedApk.ServiceDispatcher方法的connected
方法,该方法首先会判断mActivityThread对象的为空情况,实际上该对象是一个Handler且属于主线程,从前面ServiceDispatcher的创建来看,mActivityThread不会为null,因此,它会继续执行mActivityThread.post,从而实现将逻辑由服务端切换到主线程中。也就是说,ServiceConnection的回调方法,是在主线程中被回调的!相关源码如下:
// LoadedApk.ServiceDispatcher.connected()
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
// 主线程中执行
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
// LoadedApk.ServiceDispatcher.RunConnection内部类
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command) {
mName = name;
mService = service;
mCommand = command;
}
public void run() {
// command=0,
if (mCommand == 0) {
doConnected(mName, mService);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
}
在RunnConnection中,由于command=0,因此,会调用LoadedApk.ServiceDispatcher.doConnected()方法,该方法最终实现对ServiceConnection的onServiceConnected
的回调。源码如下:
// LoadedApk.ServiceDispatcher.doConnected()方法
public void doConnected(ComponentName name, IBinder service) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
if (mForgotten) {
// We unbound before receiving the connection; ignore
// any connection received.
return;
}
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
// Huh, already have this one. Oh well!
return;
}
if (service != null) {
// A new service is being connected... set it all up.
mDied = false;
info = new ConnectionInfo();
info.binder = service;
info.deathMonitor = new DeathMonitor(name, service);
try {
// 调用Service的linkToDeath
service.linkToDeath(info.deathMonitor, 0);
mActiveConnections.put(name, info);
} catch (RemoteException e) {
// This service was dead before we got it... just
// don't do anything with it.
mActiveConnections.remove(name);
return;
}
} else {
// The named service is being disconnected... clean up.
mActiveConnections.remove(name);
}
if (old != null) {
old.binder.unlinkToDeath(old.deathMonitor, 0);
}
}
// If there was an old service, it is not disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
// If there is a new service, it is now connected.
if (service != null) {
// 调用ServiceConnection的onServiceConnected
mConnection.onServiceConnected(name, service);
}
}
public void doDeath(ComponentName name, IBinder service) {
mConnection.onServiceDisconnected(name);
}
小结3:
//ActivityThread.handleStopService()
private void handleStopService(IBinder token) {
// (1)从缓存列表中移除Service对象,并返回
Service s = mServices.remove(token);
if (s != null) {
try {
if (localLOGV) Slog.v(TAG, "Destroying service " + s);
// (2)调用Service的onDestory()方法
s.onDestroy();
Context context = s.getBaseContext();
if (context instanceof ContextImpl) {
final String who = s.getClassName();
// (3)清理注册信息
// 调用mPackageInfo.removeContextRegistration()
((ContextImpl) context).scheduleFinalCleanup(who, "Service");
}
QueuedWork.waitToFinish();
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
} catch (RemoteException e) {
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to stop service " + s
+ ": " + e.toString(), e);
}
Slog.i(TAG, "handleStopService: exception for " + token, e);
}
} else {
Slog.i(TAG, "handleStopService: token=" + token + " not found.");
}
//Slog.i(TAG, "Running services: " + mServices);
}
从源码可知,该方法主要完成三件事情:
(1) 从缓存列表mServices中移除指定的Service对象;
(2) 调用Service的onDestory()方法;
(3) 调用ActivityThread的performFinalCleanup()清除Context注册信息。
final void performFinalCleanup(String who, String what) {
//Log.i(TAG, "Cleanup up context: " + this);
mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
}
private void handleUnbindService(BindServiceData data) {
// 从缓存列表获取Service对象
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
// 调用Service的onUnbind方法
boolean doRebind = s.onUnbind(data.intent);
try {
if (doRebind) {
ActivityManagerNative.getDefault().unbindFinished(
data.token, data.intent, doRebind);
} else {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to unbind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
解绑过程与绑定过程一致,最终ServiceConnection的onServiceDisconnected在主线程中被调用。