前篇:Service的启动过程
刚开始的过程和startService类似:
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
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 = 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 e.rethrowFromSystemServer();
}
}
bindServiceCommon
主要完成了两件事情:
-
通过
mPackageInfo.getServiceDispatcher
将ServiceConnection
转化成了ServiceDispatcher.InnerConnection
对象,为什么需要转换呢?这是因为服务的绑定有可能是跨进程的,所以ServiceConnection必须借助Binder机制才能让服务器来回调自己的方法,而
InnerConnection
正好实现了IServiceConnection.Stub
,转化成了Binder对象。 -
完成绑定操作。
ActivityManagerService.bindService -> ActiveServices.bindServiceLocked -> ActiveServices.bringUpServiceLocked -> ActiveServices.realStartServiceLocked
同样的和启动过程类似,都是通过ApplicationThread来创建Service的实例,并执行onCreate方法。
之后会调用requestServiceBindingsLocked
方法来绑定Service。
ActiveServices.requestServiceBindingsLocked
-> ActiveServices.requestServiceBindingLocked
-> ApplicaitonThread.scheduleBindService
同样的是通过Handler来发送BIND_SERVICE
消息
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
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);
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManagerNative.getDefault().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);
}
}
}
}
这个时候通过s.onBind(data.intent)
就将Service绑定起来了。
那么客户端是如何知道已经成功连接到Service了呢?
这个时候就要调用onServiceConnected
方法,这个过程就由publishService
来完成。
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
-> ActivityManagerService.publishService
-> ActiveServices.publishServiceLocked
在publishServiceLocked
中核心就一句c.conn.connected(r.name, service)
其中c.conn
就是一开始将ServiceConnection
转化成的ServiceDispatcher.InnerConnection
对象。
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference(sd);
}
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
}
// LoadedApk.java
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
由代码可以知道mActivityThread
是一个Handler,其实就是ActivityThread中的H,是不可能为空的,所以必定会调用post
方法。
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command) {
mName = name;
mService = service;
mCommand = command;
}
public void run() {
if (mCommand == 0) {
doConnected(mName, mService);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
}
public void doConnected(ComponentName name, IBinder service) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
// 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) {
mConnection.onServiceConnected(name, service);
}
}
由于mCommand
传的值为0,所以调用的是doConnected
方法,这个时候很方便的调用到了onServiceConnected
。
至此,Service的绑定过程就完全分析结束了。