在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);
<pre name="code" class="java">
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<ServiceConnection, LoadedApk.ServiceDispatcher> 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<ServiceConnection, LoadedApk.ServiceDispatcher>(); 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<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) { sd.connected(name, service); } } } private final HashMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections = new HashMap<ComponentName, ServiceDispatcher.ConnectionInfo>(); 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<ConnectionRecord> clist = s.connections.get(binder); if (clist == null) { clist = new ArrayList<ConnectionRecord>(); s.connections.put(binder, clist); } clist.add(c); b.connections.add(c); if (activity != null) { if (activity.connections == null) { activity.connections = new HashSet<ConnectionRecord>(); } activity.connections.add(c); } b.client.connections.add(c); .... clist = mServiceConnections.get(binder); if (clist == null) { clist = new ArrayList<ConnectionRecord>(); 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<IntentBindRecord> 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<ArrayList<ConnectionRecord>> it = r.connections.values().iterator(); while (it.hasNext()) { ArrayList<ConnectionRecord> clist = it.next(); for (int i=0; i<clist.size(); i++) { ConnectionRecord c = clist.get(i); if (!filter.equals(c.binding.intent.intent)) { .... continue; } .... try { c.conn.connected(r.name, service); } catch (Exception e) { .... } } } } } ... } } finally { ... } }
第十七步: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<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) { 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()的过程了.