在Android 中 startService()启动service的过程分析一文中讲到了startService()启动service的过程.
我们知道启动service有两种方式:startService()和bindService().两者也可以结合使用.
接下来就通过源码来分析一下bindService()的过程.
现在假设应用程序有一个activity和一个service,然后在activity中通过bindeService()启动service,清单文件中service的process属性没有设置.也就是activity和service在一个进程中.bindService()方法的参数与startService()方法参数不同,bindService()方法参数多了一个重要的参数.
bindService(intent, ServiceConnection, Context.BIND_AUTO_CREATE);
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName arg0, IBinder service) {
// TODO Auto-generated method stub
...
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
...
}
};
通过 android应用程序使用Binder实现进程间通信
, 使用aidl工具快速在应用层实现binder进程间通信
,这两篇文章我们知道,bindService()这种方式启动service,可以实现通过Binder实现进程间通信.
好了,进入主题
bindService()这个方法是Activty的父类ContextWrapper中的.
frameworks/base/core/Java/android/content/ContextWrapper.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
第一步:frameworks/base/core/java/android/app/ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
....
return bindService(service, conn, flags, UserHandle.getUserId(Process.myUid()));
}
/** @hide */
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {
IServiceConnection sd;
if (conn == null) {
...
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
} else {
....
}
try {
IBinder token = getActivityToken();//
....
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, userHandle);
if (res < 0) {
....
}
return res != 0;
} catch (RemoteException e) {
...
}
}
我们先看一下ActivityThread.getHandler的实现,然后再回到这里的bindService函数来
第二步: 在frameworks/base/core/java/android/app/ActivityThread.java中
final H mH = new H();
final Handler getHandler() {
return mH;
}
这里返回的Handler是在ActivityThread类内部从Handler类继承下来的一个H类实例变量。
回到第一步中的ContextImpl.bindService函数中,获得了这个Handler对象后,就调用mPackageInfo.getServiceDispatcher函数来获得一个IServiceConnection接口,这里的mPackageInfo的类型是LoadedApk,我们来看看它的getServiceDispatcher函数的实现,然后再回到ContextImpl.bindService函数来。
第三步:getServiceDispatcher()
frameworks/base/core/java/android/app/LoadedApk.java
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
HashMap map = mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new HashMap();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
看一下ServiceDispatcher类,是LoadedApk内部类
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final ServiceConnection mConnection;
....
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);
}
}
}
private final HashMap mActiveConnections
= new HashMap();
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;
}
void validate(Context context, Handler activityThread) {
if (mContext != context) {
....
}
if (mActivityThread != activityThread) {
.....
}
}
.....
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
.....
在getServiceDispatcher函数中,传进来的参数context是一个调用bindService的activity实例,先以它为Key值在mServices中查看一下,是不是已经存在相应的ServiceDispatcher实例,如果有了,就不用创建了,直接取出来。在我们这个情景中,需要创建一个新的ServiceDispatcher。在创建新的ServiceDispatcher实例的过程中,将上面传下来ServiceConnection参数c和Hanlder参数保存在了ServiceDispatcher实例的内部,并且创建了一个InnerConnection对象,这是一个Binder对象,一会是要传递给ActivityManagerService的,ActivityManagerServic后续就是要通过这个Binder对象和ServiceConnection通信的。
函数getServiceDispatcher最后就是返回了一个InnerConnection对象给ContextImpl.bindService函数。回到ContextImpl.bindService函数中,它接着就要调用ActivityManagerService的远程接口来进一步处理了。
回到第一步
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, userHandle);
参考分析点击android桌面app图标启动应用程序的过程这篇文章.
service.resolveTypeIfNeeded(getContentResolver())获取这个intent的MIME类型,这里假设没有设置MIME类型 即AndroidManifest.xml没有设置Service的MIME类型,所以这里返回null.
第四步:bindService()
frameworks/base/core/java/android/app/ActivityManagerNative.java
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
int flags, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeStrongBinder(token);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(connection.asBinder());
data.writeInt(flags);
data.writeInt(userId);
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
data.recycle();
reply.recycle();
return res;
}
case BIND_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
IBinder token = data.readStrongBinder();
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
int fl = data.readInt();
int userId = data.readInt();
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
int res = bindService(app, token, service, resolvedType, conn, fl, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
}
第五步:
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java.
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
....
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service, resolvedType,
connection, flags, userId);
}
}
frameworks/base/services/java/com/android/server/am/ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
.....
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
....
}
ActivityRecord activity = null;
if (token != null) {
activity = mAm.mMainStack.isInStackLocked(token);
if (activity == null) {
....
}
}
int clientLabel = 0;
PendingIntent clientIntent = null;
.....
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record;
...
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet();
}
activity.connections.add(c);
}
b.client.connections.add(c);
....
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), false) != null) {
return 0;
}
}
.....
}
函数首先根据传进来的参数token是启动service的activity在ActivityManagerService里面的一个令牌,通过这个令牌就可以将这个activity对应的的ActivityRecord取回来。
函数首先通过retrieveServiceLocked来解析service这个Intent,就是解析我们在AndroidManifest.xml定义的Service标签的intent-filter相关内容,然后将解析结果放在res.record中.
接下来,就是把传进来的参数connection封装成一个ConnectionRecord对象。注意,这里的参数connection是一个Binder对象,它的类型是LoadedApk.ServiceDispatcher.InnerConnection,是在第三步中创建的,后续ActivityManagerService就是要通过它与ServiceConnection通信,因此,这里要把这个ConnectionRecord变量c保存下来,它保在在好几个地方,都是为了后面要用时方便地取回来的,这里就不仔细去研究了,只要知道ActivityManagerService要使用它时就可以方便地把它取出来就可以了。
最后,传进来的参数flags的位Context.BIND_AUTO_CREATE为1,因此,这里会调用bringUpServiceLocked函数进一步处理。
第七步:bringUpServiceLocked();
frameworks/base/services/java/com/android/server/am/ActiveServices.java
private final String bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean whileRestarting) {
....
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
if (DEBUG_MU)
Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName);
realStartServiceLocked(r, app);
return null;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
} else {
...
}
....
}
这里service所在的进程已经启动起来了,所以接下来直接在这个进程中启动service.
第八步:realStartServiceLocked();
frameworks/base/services/java/com/android/server/am/ActiveServices.java
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app) throws RemoteException {
...
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
app.services.add(r);
bumpServiceExecutingLocked(r, "create");
mAm.updateLruProcessLocked(app, true);
boolean created = false;
try {
....
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
r.postNotification();
created = true;
} finally {
....
}
requestServiceBindingsLocked(r);
.....
sendServiceArgsLocked(r, true);
}
①scheduleCreateService()
②requestServiceBindingsLocked()
③sendServiceArgsLocked()
这里①就不分析了,和Android 中 startService()启动service的过程分析的第七步至第十步一样的.首先创建service,即service的onCreate()方法会被调用.
好了,我们看②
第九步:requestServiceBindingsLocked();
frameworks/base/services/java/com/android/server/am/ActiveServices.java
private final void requestServiceBindingsLocked(ServiceRecord r) {
Iterator bindings = r.bindings.values().iterator();
while (bindings.hasNext()) {
IntentBindRecord i = bindings.next();
if (!requestServiceBindingLocked(r, i, false)) {
break;
}
}
}
private final boolean requestServiceBindingLocked(ServiceRecord r,
IntentBindRecord i, boolean rebind) {
....
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, "bind");
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (RemoteException e) {
....
}
}
return true;
}
这里的参数r就是我们在前面的
第六步
中创建的ServiceRecord了,它代表创建的service。函数requestServiceBindingsLocked调用了requestServiceBindingLocked函数来处理绑定服务的操作,而函数requestServiceBindingLocked又调用了app.thread.scheduleBindService函数执行操作,前面我们已经介绍过app.thread,它是一个Binder对象的远程接口,类型是ApplicationThreadProxy。
第十 步:scheduleBindService();
frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中,这里又是Binder进程间通信了.
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
intent.writeToParcel(data, 0);
data.writeInt(rebind ? 1 : 0);
mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
经过Binder驱动
case SCHEDULE_BIND_SERVICE_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
IBinder token = data.readStrongBinder();
Intent intent = Intent.CREATOR.createFromParcel(data);
boolean rebind = data.readInt() != 0;
scheduleBindService(token, intent, rebind);
return true;
}
第十一步:scheduleBindService();
在frameworks/base/core/java/android/app/ActivityThread.java中
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind) {
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
if (DEBUG_SERVICE)
Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
queueOrSendMessage(H.BIND_SERVICE, s);
}
在frameworks/base/core/java/android/app/ActivityThread.java中
private void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, obj, 0, 0);
}
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
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;
mH.sendMessage(msg);
}
}
在frameworks/base/core/java/android/app/ActivityThread.java中
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 (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);//
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
....
}
ensureJitEnabled();
} catch (RemoteException ex) {
}
} catch (Exception e) {
....
}
}
}
第十四步:publishService();
这里通过Binder进程通信,调用到ActivityManagerService中去,参数中有上一步创建的Binder对象.
中间通信步骤就省略了,和第四步类似.
第十五步:publishService();
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java.
public void publishService(IBinder token, Intent intent, IBinder service) {
...
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
....
}
第十六步:
publishServiceLocked();
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
...
try {
....
if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
b.binder = service;
b.requested = true;
b.received = true;
if (r.connections.size() > 0) {
Iterator> it
= r.connections.values().iterator();
while (it.hasNext()) {
ArrayList clist = it.next();
for (int i=0; i
第十七步:InnerConnection.connected();
frameworks/base/core/java/android/app/LoadedApk.java
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final ServiceConnection mConnection;
.....
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);
}
}
}
这里它将操作转发给ServiceDispatcher.connected函数。
第十七步:ServiceDispatcher.connected();
frameworks/base/core/java/android/app/LoadedApk.java
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
...
}
}
我们在前面
第三步
中说到,这里的mActivityThread是一个Handler实例,它是通过ActivityThread.getHandler函数得到的,因此,调用它的post函数后,就会把一个消息放到ActivityThread的消息队列中去了。
第十八步:H.post;
由于H类继承于Handler类,因此,这里实际执行的Handler.post函数,这个函数定义在frameworks/base/core/java/android/os/Handler.java文件,调用了这个函数之后,这个消息就真正地进入到ActivityThread的消息队列去了,与sendMessage把消息放在消息队列不一样的地方是,post方式发送的消息不是由这个Handler的handleMessage函数来处理的,而是由post的参数Runnable的run函数来处理的。这里传给post的参数是一个RunConnection类型的参数,它继承了Runnable类,因此,最终会调用RunConnection.run函数来处理这个消息。
第十九步: RunConnection.run
frameworks/base/core/java/android/app/LoadedApk.java
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;
}
这里的mCommand值为0,于是就执行ServiceDispatcher.doConnected函数来进一步操作了。
第二十步: ServiceDispatcher.doConnected
frameworks/base/core/java/android/app/LoadedApk.java
public void doConnected(ComponentName name, IBinder service) {
....
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
mConnection.onServiceConnected(name, service);这个回调大家应该也很熟悉吧,这里就把service这个Binder对象传到activity中来了.
好了,到这一步,service 已经onCreate()和onBind()了,同时,绑定服务时,服务返回的Binder对象也接收到了,
然后回到第八步.③也不分析了,和Android 中 startService()启动service的过程分析的第十一步至第十三步一样的.即service的onStart()方法和onStartCommand()会被调用.
上面就是bindService()的过程了.