Service启动流程
在context中一句startService()之后发生了什么
Service 有绑定和启动两种调动形式
启动Service

1、通过contextWrapper的mBase来实现startService方法,转到startServiceCommon,然后通过ActivityManagerServiceNative.getDefault()这个对象来启动服务,它实际就是AMS。
2、上述对AMS.startService()方法是远程调动,在该方法中,AMS借助ActiveService这个辅助类来管理service的启动绑定停止等。其最后调用startServiceInnerLocked()
3、上述方法转入bringUpServiceLocked(),最后跳转到realStartServiceLocked()进行具体的service启动实现
4、在realStartServiceLocked中首先通过app.thread.scheduleCreateService()方法其实现类似于activity的启动,通过远程调用在APP的ApplicationThread中实现,并通过H传递消息到ActivityThread,具体处理方法为handleCreateService(),主要做了创建Service实例,创建Application对象并调用其onCreate(如果存在就不会调用),接着创建ContextImpl对象并通过Service.attach方法建立二者之间的联系,这个过程类似于activity的,最后调用Service的onCreate方法。然后service会被存储到activityThread的一个列表中,这个列表是一个ArrayMap叫做mServices。
5、Service已经被创建了,后面通过类似的进程间通信流程调用service的onStartCommand方法。
绑定Service

1、和启动service一样,从ContextWrapper开始bindService,最终调用contextImpl的bindServiceCommon()方法,
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, 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(this);
int res = ActivityManager.getService().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 e.rethrowFromSystemServer();
}
}
mPackageInfo是一个LoadedApk实例对象,getServiceDispatcher()返回的是一个LoadedApk的静态内部类ServiceDispatcher中的InnerConnection对象,InnerConnection是ServiceDispatcher中的静态内部类,继承 了IServiceConnection.Stub。接下来看下getServiceDispatcher的实现
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);
if (map != null) {
if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
可见serviceDIspatcher内部同时封装了serviceConnection和InnerConnection,起着连接两者的作用。如果存在相同的serviceConnection系统就会复用map中的sd。服务的调用可能是跨进程的,所以当Service和客户端完成连接后,ServiceConnection(定义在客户端)需要binder才能让远程服务端调用自己的方法,InnerConnection恰好充当了binder这个角色。
继续上述bindServiceCommon方法,AMS通过bindService方法完成具体绑定过程。
2、后续在AMS服务端调用ActiveService的bindServiceLocked方法,依次跳转到bringUpSericeLocked,realStartServiceLocked方法,后续流程和启动service类似。通过ApplicationThread完成Service的创建并执行其onCreate方法,不同的是Service绑定过程还会调用app.Thread.scheduleServiceLocked方法,这个实现方法在requestServiceBindingLocked中。
3、然后通过ApplicationThread到ActvityThread的handleBindService处理。
private void handleBindService(BindServiceData data) {
//在前面成功执行onCreate后,会通过mServices.put()保存service
//mServices是一个ArrayMap对象
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
//执行onBind()
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
原则上说,执行onBind之后service就已经和客户端连接上了,但是这是service自己的方法,客户端还不知道,所以需要回调客户端的ServiceConnection的onServiceConnected(),这个过程实现通过AMS的plushService()实现。
此外多次绑定同一个Service,其onBind方法只会执行一次,除非service被终止了。
4、对于上述plushService方法,交给ActiveServices的plushServiceLocked方法来处理,核心过程是c.conn.connected(r.name,service),c是CoonectionRcord,c.conn的类型是SericeDispatcher.InnerConnection,service就是Service的onBind方法返回额binder对象。
5、在innerConnection中的connected方法具体实现是其引用的ServiceDispatcher.connected方法。该方法核心语句是mActivityThread.post(new RunConnection(name,service,0));mActivityThread就是ActivityThread.H,这样客户端ServiceConnection的方法就是在主线程被回调的。RunConnection中的run方法其实是简单调用了ServiceDispather的doConnected,前面已经描述,ServiceDispather内部保存了客户端的ServiceConnection对象,所以可以轻松地调用ServiceConnection中的公共方法。
Service的停止和接触绑定过程,和上述类似。