前言
Service作为四大组件中较常用的组件,通常和各种需要后台执行的业务相关连。Service有两种启动方法startService/bindService,对应的停止操作也分成两种stopService/unbindService,现在来阅读下Android的实现源码深入理解Service的工作原理过程。
startService/StopService分析
startService方法并没有被定义在Activity中,而是定义在ContextImpl这个类里,查看startService源码会发现实际上调用的是startServiceCommon这个方法实现。
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
startServiceCommon方法直接调用了ActivityManager向ActivityManagerService(AMS)服务请求创建新的服务。AMS服务通过mMainThread.getApplicationThread()这个binder对象通知ActivityThread要创建一个新的Service。
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
...
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
查看ActivityThread里的H类里处理CREATE_SERVICE消息的回调调用了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;
// 通过反射生成Service对象
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
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);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
// 获取Application对象并且attach到Service中
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 执行Service的onCreate方法
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
相比较创建Activity的过程创建Service要简单的多,实现并不复杂,接着ActivityManager.getService().serviceDoneExecuting()通知AMS当前的Service已经启动,这个时候AMS会继续发送SERVICE_ARGS消息过来,H类里的对应处理方法为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();
}
// 调用onStartCommand方法
int res;
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
ensureJitEnabled();
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to start service " + s
+ " with " + data.args + ": " + e.toString(), e);
}
}
}
}
handleServiceArgs方法会调用已经创建启动的Service对象的onStartCommand方法。Service启动过程比起Activity的启动简明了很多,现在来看Service.stopService操作。
@Override
public boolean stopServiceAsUser(Intent service, UserHandle user) {
return stopServiceCommon(service, user);
}
private boolean stopServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
int res = ActivityManager.getService().stopService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to stop service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
stopServiceCommon里也是调用ActivityManager向AMS发送stopService请求,在ActivityThread里查看STOP_SERVICE消息里回调了handleStopService((IBinder)msg.obj);方法。
private void handleStopService(IBinder token) {
Service s = mServices.remove(token);
if (s != null) {
try {
if (localLOGV) Slog.v(TAG, "Destroying service " + s);
s.onDestroy();
s.detachAndCleanUp();
Context context = s.getBaseContext();
if (context instanceof ContextImpl) {
final String who = s.getClassName();
((ContextImpl) context).scheduleFinalCleanup(who, "Service");
}
QueuedWork.waitToFinish();
try {
ActivityManager.getService().serviceDoneExecuting(
token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} 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);
}
handleStopService方法主要调用了Service的onDestroy回调并且通知AMS自己被停止。
bindService/unbindService
ContextImpl里的各种bindService最终调用的是bindServiceCommon这个方法的实现,如果调用过bindService应该知道其中会传递一个ServiceConnection对象,这个对象负责将与服务相关的binder对象返回到客户端。
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);
// 通过ActivityManager向AMS请求绑定到Service
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();
}
}
这里使用ServiceDispather对象包装了ServiceConnection对象,并且将ServiceDispatcher对象传递到了AMS端。
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;
}
ServiceDispatcher对象内部包含了一个InnerConnection也是一个Binder,AMS就是通过这个Binder对象将启动服务的Binder传递回客户端。
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, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
在AMS启动后同时会调用ApplicationThread回调通知ActivityThread绑定Service成功,这时后Service对应的binder对象会同时发布到ActivityManagerService里。
private void handleBindService(BindServiceData data) {
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) {
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);
}
}
}
}
当AMS通知connected调用的时候会直接调用ServiceDispatcher.connected方法,这个方法里又会调用doConnected方法,在最后会调用ServiceConnection.onServiceConnected将Service对应的Binder返回到客户端中。
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
....
if (dead) {
mConnection.onBindingDied(name);
}
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
接着查看unbindService方法直接调用ActivityManager向AMS发送unbindService的请求。
@Override
public void unbindService(ServiceConnection conn) {
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
getOuterContext(), conn);
try {
ActivityManager.getService().unbindService(sd);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} else {
throw new RuntimeException("Not supported in system context");
}
}
AMS在ApplicationThread返回UNBIND_SERVICE消息,在H的消息回调中调用了handleUnbindService,最后调用Service.onUnbind回调。
private void handleUnbindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
boolean doRebind = s.onUnbind(data.intent);
try {
if (doRebind) {
ActivityManager.getService().unbindFinished(
data.token, data.intent, doRebind);
} else {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to unbind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
总结
Service启动过程相对Activity简单了很多,startService直接向ActivityManagerService(AMS)发送启动Service的请求AMS创建了Service内核数据结构之后就发送CREATE_SERVICE通知ActivityThread启动Service,开始执行Service.onCreate方法,执行完成后通知AMS已经启动成功,AMS再发送SERVICE_ARGS回调Service.onStartCommand方法,以后再执行startService都AMS都会只发送SERVICE_ARGS通知,stopService会通过ActivityManager告知AMS Activity要停止,AMS会处理内核里的Activity数据结构,之后在发送SERVICE_STOP通知给ActivityThread,最后调用Service.onDestroy方法。
bindService相对来说又比startService多了一个返回Service的binder对象回调功能。ActivityManager请求bindService是会将ApplicationThread和ServiceDispatcher传递给AMS,AMS首先发送给ActivityThread SERVICE_CREATE通知,Service执行onCreate方法,通知AMS Service创建成功,AMS再发送SERVICE_BIND消息给ActivityThread这时回调onBind方法,再通知AMS绑定操作成功,AMS通过InnerConnection向ServiceDispatcher发送onConnected回调,ServiceDispatcher内部再调用ServiceConnection将Service绑定的binder回调给客户端。unBindService基本和stopService一致,不再赘述。