接着上一篇StartService,这章分析一下bindService的一个流程。
在Android developer网站上有三种使用创建Bound Service的方法:
一种就是继承Binder Class的,这种方法用在当你的Service只会用在自己的进程当中,而不会出现换进程的调用。也就是所谓的LocalService.
一种是使用Messager,这是通过使用Handler相关的东西,去实现跨进程的调用。
最后一种就是AIDL,最常用的一种跨进程的Service binder调用。
1. ContextImpl.bindService()
通常我们想去调用一个Service的时候,会传递一个Intent和一个ServiceConnection还有一个flags参数。ServiceConnection是需要我们继承的。
flags:Operation options for the binding
1. 通过mPackageInfo.getServiceDispatcher(conn, getOuterContext(),mMainThread.getHandler(), flags);
2. 通过ActivityManagerNative去远程调用AMS。
public boolean bindService(Intent service, ServiceConnection conn,int flags) { warnIfCallingFromSystemProcess(); return bindService(service, conn, flags, UserHandle.getUserId(Process.myUid())); } /** @hide */ @Override public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) { IServiceConnection sd; try { IBinder token = getActivityToken(); if (mPackageInfo != null) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), mMainThread.getHandler(), flags); ... ... int res = ActivityManagerNative.getDefault().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, userHandle); ... ... return res != 0; } catch (RemoteException e) { return false; } }
1.1 LoaderApk.getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)
在ServiceDispatcher会保存着传进来的ServiceConnection,同时有一个InnerConnection对象,而InnerConnection是继承自IServiceConnection.Stub,所以InnerConnection是一个Binder的服务端。sd.getIServiceConnection()返回的就是InnerConnection对象mIServiceConnection。
里面有两个Map数组,一个context对应一组(ServiceConnection和ServiceDispatcher的map),一个ServiceConnection对应一个ServiceDispatcher。
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(); } }
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; }
1. 直接调用mServices.bindServiceLocked
public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) { enforceNotIsolatedCaller("bindService"); // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, userId); } }
2.1 ActiveService.bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, int userId)
1. 通过传进来的token值到ActivityStack中查询该token值是不是已经有了,就是调用者Activity的 ActivityRecord
2. 通过retrieveServiceLocked找到需要bind的service放到新的ServiceRecord中
3. 新建AppBindRecord, ConnectionRecord, 获取Clinet端传过来的ServiceDispatcher.InnerConnection的IBinder,把IBinder与ConnectionRecord建立关系并保持在对应的connections中。
4. bringUpServiceLocked, 启动Service // goto 2.1.4
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) { ActivityRecord activity = null; if (token != null) { activity = mAm.mMainStack.isInStackLocked(token); if (activity == null) { Slog.w(TAG, "Binding with unknown activity: " + token); return 0; } } ... ... int clientLabel = 0; PendingIntent clientIntent = null; ... ... ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, Binder.getCallingPid(), Binder.getCallingUid(), userId, true); ServiceRecord s = res.record; try { 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); if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) { b.client.hasAboveClient = true; } 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; } } if (s.app != null) { // This could have made the service more important. mAm.updateOomAdjLocked(s.app); } if (s.app != null && b.intent.received) { // Service is already running, so we can immediately // publish the connection. try { c.conn.connected(s.name, b.intent.binder); } catch (Exception e) { Slog.w(TAG, "Failure sending service " + s.shortName + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } // If this is the first app connected back to this binding, // and the service had previously asked to be told when // rebound, then do so. if (b.intent.apps.size() == 1 && b.intent.doRebind) { requestServiceBindingLocked(s, b.intent, true); } } else if (!b.intent.requested) { requestServiceBindingLocked(s, b.intent, false); } } finally { Binder.restoreCallingIdentity(origId); } return 1; }
1. 如果这个Service所在的进程已经起来了,就直接调用realStartServiceLocked(r, app); 如果这个Service还没有起来就先去mAm.startProcessLocked启动对应的process,然后把需要start的service添加到mPendingServices中,等到进程起来之后会调用attachApplicationLocked去启动相应的service,当然还是调用realStartServiceLocked(sr, proc);
private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean whileRestarting) { // Service is now being launched, its package can't be stopped. try { AppGlobals.getPackageManager().setPackageStoppedState( r.packageName, false, r.userId); } catch (RemoteException e) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + r.packageName + ": " + e); } 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 { // If this service runs in an isolated process, then each time // we call startProcessLocked() we will get a new isolated // process, starting another process if we are currently waiting // for a previous process to come up. To deal with this, we store // in the service any current isolated process it is running in or // waiting to have come up. app = r.isolatedProc; } if (!mPendingServices.contains(r)) { mPendingServices.add(r); } return null; }
2.1.4.1 ActiveService.realStartServiceLocked(ServiceRecord r, ProcessRecord app)
app.services.add(r); //把record加到service所在的进程的ProcessRecord的services的数组中
bumpServiceExecutingLocked(r, "create"); // 把service加到 r.app.executingServices中,说明这个servcie正在执行。
1) app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo)); 通过app.thread.scheduleCreateService去调用ActivityThread的scheduleCreateService。在ActivityThread的中通过handle去发送和处理“CREATE_SERVICE”的消息。调用handleCreateService
2) requestServiceBindingLock() //这个函数在BindService的时候才会起作用
3) sendServiceArgsLocked(r, true); //没有传递的参数,在这边没用
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app) throws RemoteException { ... ... app.services.add(r); bumpServiceExecutingLocked(r, "create"); mAm.updateLruProcessLocked(app, true); boolean created = false; try { ... ... EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE, r.userId, System.identityHashCode(r), r.shortName, mAm.mStringBuilder.toString(), r.app.pid); synchronized (r.stats.getBatteryStats()) { r.stats.startLaunchedLocked(); } mAm.ensurePackageDexOpt(r.serviceInfo.packageName); app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo)); r.postNotification(); created = true; } finally { if (!created) { app.services.remove(r); scheduleServiceRestartLocked(r, false); } } requestServiceBindingsLocked(r); // If the service is in the started state, and there are no // pending arguments, then fake up one so its onStartCommand() will // be called. if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), null, null)); } sendServiceArgsLocked(r, true); }
1) 调用 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind); 去调用ActivityThread的方法
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 (r.app == null || r.app.thread == null) { // If service is not currently running, can't yet bind. return false; } 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) { if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r); return false; } } return true; }
1) 找到对应的Service,并且调用Service.onBind(自己写的Service都是要实现onBind来返回一个IBinder用来与之交互的), 把返回的IBinder值传回ActiveService, 调用 ActivityManagerNative.getDefault().publishService( data.token, data.intent, binder);
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()); 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, 0, 0, 0); } ensureJitEnabled(); } catch (RemoteException ex) { } } catch (Exception e) { ... ... } }
里面的细节先不关注,这里主要看c.conn.connected(r.name, service); 这个就调到我们之前传进来的ServiceDispatcher.InnerConnection的connected(), 最终就用调用mConnection.onServiceConnected(name, service); 也就是ServiceConnection.onServiceConnected。
ServiceConnection.onServiceConnected传进来的Binder就是Service.onBind()返回的值。
所以这就建立了ServiceConnection与Service之间的关系。
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r + " " + intent + ": " + service); 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)) { if (DEBUG_SERVICE) Slog.v( TAG, "Not publishing to: " + c); if (DEBUG_SERVICE) Slog.v( TAG, "Bound intent: " + c.binding.intent.intent); if (DEBUG_SERVICE) Slog.v( TAG, "Published intent: " + intent); continue; } if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c); try { c.conn.connected(r.name, service); } catch (Exception e) { Slog.w(TAG, "Failure sending service " + r.name + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } } } } } serviceDoneExecutingLocked(r, mStoppingServices.contains(r)); } } finally { Binder.restoreCallingIdentity(origId); } }
3. ContextImpl.unbindSercie
1) 通过ActivityManagerNative.getDefault().unbindService(sd); 调用ActiveServices.unbindServiceLocked
public void unbindService(ServiceConnection conn) { if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (mPackageInfo != null) { IServiceConnection sd = mPackageInfo.forgetServiceDispatcher( getOuterContext(), conn); try { ActivityManagerNative.getDefault().unbindService(sd); } catch (RemoteException e) { } } else { throw new RuntimeException("Not supported in system context"); } }
1) 根据传进来的ServiceDispatcher.InnerConnection的IBinder值获取对应的ConnectionRecord的list,然后依次调用removeConnectionLocked(r, null, null);
boolean unbindServiceLocked(IServiceConnection connection) { IBinder binder = connection.asBinder(); if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder); ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder); if (clist == null) { Slog.w(TAG, "Unbind failed: could not find connection for " + connection.asBinder()); return false; } final long origId = Binder.clearCallingIdentity(); try { while (clist.size() > 0) { ConnectionRecord r = clist.get(0); removeConnectionLocked(r, null, null); if (r.binding.service.app != null) { // This could have made the service less important. mAm.updateOomAdjLocked(r.binding.service.app); } } } finally { Binder.restoreCallingIdentity(origId); } return true; }
1) s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); 回调ActivityThread的handleUnbindService,在这个函数中会去s.onUnbind 去做service unBind的动作。
2) bringDownServiceLocked(s, false);
void removeConnectionLocked( ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) { IBinder binder = c.conn.asBinder(); AppBindRecord b = c.binding; ServiceRecord s = b.service; ArrayList<ConnectionRecord> clist = s.connections.get(binder); if (clist != null) { clist.remove(c); if (clist.size() == 0) { s.connections.remove(binder); } } b.connections.remove(c); if (c.activity != null && c.activity != skipAct) { if (c.activity.connections != null) { c.activity.connections.remove(c); } } if (b.client != skipApp) { b.client.connections.remove(c); if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) { b.client.updateHasAboveClientLocked(); } } clist = mServiceConnections.get(binder); if (clist != null) { clist.remove(c); if (clist.size() == 0) { mServiceConnections.remove(binder); } } if (b.connections.size() == 0) { b.intent.apps.remove(b.client); } if (!c.serviceDead) { if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent + ": shouldUnbind=" + b.intent.hasBound); if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0 && b.intent.hasBound) { try { bumpServiceExecutingLocked(s, "unbind"); mAm.updateOomAdjLocked(s.app); b.intent.hasBound = false; // Assume the client doesn't want to know about a rebind; // we will deal with that later if it asks for one. b.intent.doRebind = false; s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); } catch (Exception e) { Slog.w(TAG, "Exception when unbinding service " + s.shortName, e); serviceDoneExecutingLocked(s, true); } } if ((c.flags&Context.BIND_AUTO_CREATE) != 0) { bringDownServiceLocked(s, false); } } }
1) 如果force == false也就是并没有要求强制退出,r.connections.size() > 0 说明 这个Service还有其他Client Bind存在就直接return; 要不然r.connections.size() == 0, 说明多有的Client端都已经调用了unbind了,此时就会去把这个Service给destroy掉,通过调用r.app.thread.scheduleStopService(r);
此时s.onDestroy();就会被调用,也就是一个Service的生命周期结束。
2) mStoppingServices.add(r); //加到mStoppingServices数组中。
private final void bringDownServiceLocked(ServiceRecord r, boolean force) { //Slog.i(TAG, "Bring down service:"); //r.dump(" "); // Does it still need to run? if (!force && r.startRequested) { return; } if (r.connections.size() > 0) { if (!force) { // XXX should probably keep a count of the number of auto-create // connections directly in the service. Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator(); while (it.hasNext()) { ArrayList<ConnectionRecord> cr = it.next(); for (int i=0; i<cr.size(); i++) { if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) { return; } } } } // Report to all of the connections that the service is no longer // available. Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator(); while (it.hasNext()) { ArrayList<ConnectionRecord> c = it.next(); for (int i=0; i<c.size(); i++) { ConnectionRecord cr = c.get(i); // There is still a connection to the service that is // being brought down. Mark it as dead. cr.serviceDead = true; try { cr.conn.connected(r.name, null); } catch (Exception e) { Slog.w(TAG, "Failure disconnecting service " + r.name + " to connection " + c.get(i).conn.asBinder() + " (in " + c.get(i).binding.client.processName + ")", e); } } } } ... ... if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent); EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE, r.userId, System.identityHashCode(r), r.shortName, (r.app != null) ? r.app.pid : -1); mServiceMap.removeServiceByName(r.name, r.userId); mServiceMap.removeServiceByIntent(r.intent, r.userId); r.totalRestartCount = 0; unscheduleServiceRestartLocked(r); // Also make sure it is not on the pending list. int N = mPendingServices.size(); for (int i=0; i<N; i++) { if (mPendingServices.get(i) == r) { mPendingServices.remove(i); if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r); i--; N--; } } r.cancelNotification(); r.isForeground = false; r.foregroundId = 0; r.foregroundNoti = null; // Clear start entries. r.clearDeliveredStartsLocked(); r.pendingStarts.clear(); if (r.app != null) { synchronized (r.stats.getBatteryStats()) { r.stats.stopLaunchedLocked(); } r.app.services.remove(r); if (r.app.thread != null) { try { bumpServiceExecutingLocked(r, "stop"); mStoppingServices.add(r); mAm.updateOomAdjLocked(r.app); r.app.thread.scheduleStopService(r); } catch (Exception e) { ... ... } else { if (DEBUG_SERVICE) Slog.v( TAG, "Removed service that has no process: " + r); } } else { if (DEBUG_SERVICE) Slog.v( TAG, "Removed service that is not running: " + r); } ... ... }
3.1.1.2.1 ActivityThread.handleStopService
当handleStopService执行完后,还是会调用ActiveServices.serviceDoneExecutingLocked告诉AMS客户端已经执行完成了。
此时inStopping为true,因为这个ServiceRecord已经加到mStoppingServices中
void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) { boolean inStopping = mStoppingServices.contains(r); if (r != null) { ... ... final long origId = Binder.clearCallingIdentity(); serviceDoneExecutingLocked(r, inStopping); Binder.restoreCallingIdentity(origId); } else { Slog.w(TAG, "Done executing unknown service from pid " + Binder.getCallingPid()); } }
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) { if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r + ": nesting=" + r.executeNesting + ", inStopping=" + inStopping + ", app=" + r.app); else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName); r.executeNesting--; if (r.executeNesting <= 0 && r.app != null) { if (DEBUG_SERVICE) Slog.v(TAG, "Nesting at 0 of " + r.shortName); r.app.executingServices.remove(r); if (r.app.executingServices.size() == 0) { if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "No more executingServices of " + r.shortName); mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app); } if (inStopping) { if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r); mStoppingServices.remove(r); r.bindings.clear(); } mAm.updateOomAdjLocked(r.app); } }