Service的工作过程
2016-04-26 13:56
323 查看
Service的工作过程
Service分为两种工作状态,一种是启动状态,主要用于执行后台计算;另一种是绑定状态,主要用于其他组件和Service的交互。这两种状态可以共存的,即Service既可以处于启动状态也可以同时处于绑定状态。本篇博客是对Service的启动过程和绑定过程进行源码分析。
介绍一下几个重要的概念:
1. Context:/article/1390930.html
2. ActivityThread、ApplicationThread:/article/7801256.html
Service的启动过程
从ContextWrapper的startService开始:@Override public ComponentName startService(Intent service) { return mBase.startService(service); }
mBase的类型是ContextImpl。
@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, mUser); } private ComponentName startServiceCommon(Intent service, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(); ComponentName cn = ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), getOpPackageName(), user.getIdentifier()); if (cn != null) { if (cn.getPackageName().equals("!")) { throw new SecurityException( "Not allowed to start service " + service + " without permission " + cn.getClassName()); } else if (cn.getPackageName().equals("!!")) { throw new SecurityException( "Unable to start service " + service + ": " + cn.getClassName()); } } return cn; } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } }
由上可知,startServiceCommon通过ActivityManagerNative.getDefault()(AMS)这个对象启动一个Service。通过AMS来启动服务的行为是一个远程调用过程。
AMS#startService
@Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("startService"); // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } if (callingPackage == null) { throw new IllegalArgumentException("callingPackage cannot be null"); } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "startService: " + service + " type=" + resolvedType); synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, callingPackage, userId); Binder.restoreCallingIdentity(origId); return res; } }
AMS会通过mService来完成Service后续的启动过程,mService对象的类型是ActivityServices,是一个辅助AMS进行Service管理的类,包括Service的启动、绑定和停止等。在ActivityServices的startServiceLocked方法会调用startServiceInnerLocked方法,startServiceInnerLocked方法继续调用bringUpServiceLocked方法,bringUpServiceLocked方法又调用realStartServiceLocked方法。
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { if (app.thread == null) { throw new RemoteException(); } if (DEBUG_MU) Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid + ", ProcessRecord.uid = " + app.uid); r.app = app; r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); final boolean newService = app.services.add(r); bumpServiceExecutingLocked(r, execInFg, "create"); mAm.updateLruProcessLocked(app, false, null); mAm.updateOomAdjLocked(); boolean created = false; try { if (LOG_SERVICE_START_STOP) { String nameTerm; int lastPeriod = r.shortName.lastIndexOf('.'); nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName; EventLogTags.writeAmCreateService( r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid); } synchronized (r.stats.getBatteryStats()) { r.stats.startLaunchedLocked(); } mAm.ensurePackageDexOpt(r.serviceInfo.packageName); app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); r.postNotification(); created = true; } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app); throw e; } finally { if (!created) { // Keep the executeNesting count accurate. final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); // Cleanup. if (newService) { app.services.remove(r); r.app = null; } // Retry. if (!inDestroying) { scheduleServiceRestartLocked(r, false); } } } requestServiceBindingsLocked(r, execInFg); updateServiceClientActivitiesLocked(app, null, true); // 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, execInFg, true); if (r.delayed) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r); getServiceMap(r.userId).mDelayedStartList.remove(r); r.delayed = false; } if (r.delayedStop) { // Oh and hey we've already been asked to stop! r.delayedStop = false; if (r.startRequested) { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Applying delayed stop (from start): " + r); stopServiceLocked(r); } } }
在realStartServiceLocked方法中,首先通过app.thread的scheduleCreateService方法来创建Service对象并调用其onCreate,接着调用sendServiceArgsLocked方法来调用Service的其他方法,比如onStartCommand,这两个过程均是进程间的通信。具体实现是ApplicationThread。
ApplicationThread#scheduleCreateService
public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false); CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s); }
这个过程和Activity的启动类似。发送消息给Handler H,H接受消息H.CREATE_SERVICE并通过ActivityThread的handleCreateService方法来完成Service的启动。
ActivityThread#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; 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 app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); service.onCreate(); mServices.put(data.token, service); try { ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { // nothing to do. } } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } }
主要完成了以下四件事:
1. 首先通过类加载器创建Service的实例
2. 然后创建Appliction对象并调用其onCreate
3. 接着调用ContextImpl对象并通过Service的attach方法建立二者的关系,和Activity的类似。
4. 最后调用Service的onCreate方法并将Service对象存储到ActivityThread中的一个列表中。
由于Service的onCreate被执行,意味着Service已经启动,除此之外,ActivityThread中还会通过handleServiceArgs方法调用Service的onStartCommand方法。
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(); } 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 { ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_START, data.startId, res); } catch (RemoteException e) { // nothing to do. } ensureJitEnabled(); } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to start service " + s + " with " + data.args + ": " + e.toString(), e); } } } }
Service的绑定过程
Service的绑定过程也是从ContextWrapper开始。@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { return mBase.bindService(service, conn, flags); }
ContextImpl#bindServiceCommon
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, UserHandle user) { IServiceConnection sd; if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (mPackageInfo != null) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), mMainThread.getHandler(), 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(); 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 new RuntimeException("Failure from system", e); } }
首先将客户端的ServiceConnection对象转化为ServiceDispather.InnerConnection对象。因为服务的绑定有可能是跨进程的,ServiceConnection必须借助Binder才能让远程服务端回调自己的方法,ServiceDispather.InnerConnection刚好充当了Binder。ServiceDispather起连接ServiceConnection和InnerConnection的作用。此过程由LoadedApk的getServiceDispather方法完成。
LoadedApk#getServiceDispather
public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) { synchronized (mServices) { LoadedApk.ServiceDispatcher sd = null; ArrayMap<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 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler); } return sd.getIServiceConnection(); } }
mService是一个ArrayMap存储了一个应用当前活动的ServiceConnection和ServiceDispatcher的映射关系。
系统首先会查找是否存在相同的ServiceConnection,若不存在,则重新创建一个ServiceDispatcher对象并将其存储在mService中,在ServiceDispatcher内部又保存了ServiceConnection和InnerConnection对象。当Service和客户端建立连接后,系统会通过InnerConnection来调用ServiceConnection中的onServiceConnected方法,这个过程可能跨进程。当ServiceDispatcher创建好以后,getServiceDispatcher会返回其保存的InnerConnection对象。
AMS#bindService
public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("bindService"); // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } if (callingPackage == null) { throw new IllegalArgumentException("callingPackage cannot be null"); } synchronized(this) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, callingPackage, userId); } }
接下来AMS会调用ActivityServices的startServiceLocked方法。在ActivityServices的startServiceLocked方法会调用startServiceInnerLocked方法,startServiceInnerLocked方法继续调用bringUpServiceLocked方法,bringUpServiceLocked方法又调用realStartServiceLocked方法。最终通过ApplicationThread来完成Service实例的创建并执行onCreate方法,和启动Service不同的是,Service的绑定过程会调用app.thread的scheduleBindService方法。
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { updateProcessState(processState, false); 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()); sendMessage(H.BIND_SERVICE, s); }
在H内部收到BIND_SERVICE,会交给ActivityThread的handleBindService方法来处理。
ActivityThread#handleBindService
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) { } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to bind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } }
在handleBindService中,首先根据Service的token取出Service对象,然后调用Service的onBind方法,Service的onBind方法返回一个Binder对象给客户端使用。原则上来说,Service的onBind方法调用后Service就被绑定成功,但是onBind方法是Service的方法,这个时候客户端并不知道已经成功连接Service,所以还要调用客户端的ServiceConnection中的onServiceConnected,这是由AMS的publishService方法完成。
Service有一个特性,当多次绑定同一个Service时,Service的onBind方法只会执行一次,除非Service被终止。当Service的onBind执行以后,系统还需要告知客户端已经成功连接Service了。由AMS的publishService方法完成。
AMS#publishService
public void publishService(IBinder token, Intent intent, IBinder service) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { if (!(token instanceof ServiceRecord)) { throw new IllegalArgumentException("Invalid service token"); } mServices.publishServiceLocked((ServiceRecord)token, intent, service); } }
由上可知,AMS的publishService方法将具体的工作交给了ActiveServices类型的mService对象来处理。
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "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; for (int conni=r.connections.size()-1; conni>=0; conni--) { ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni); 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_SERVICE, "Not publishing to: " + c); if (DEBUG_SERVICE) Slog.v( TAG_SERVICE, "Bound intent: " + c.binding.intent.intent); if (DEBUG_SERVICE) Slog.v( TAG_SERVICE, "Published intent: " + intent); continue; } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "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, mDestroyingServices.contains(r), false); } } finally { Binder.restoreCallingIdentity(origId); }
核心代码
c.conn.connected(r.name, service);其中c是ConnectionRecord;c.conn是ServiceDispatcher.InnerConnection,Service就是Service的onBind返回的Binder对象。
LoadedApk#ServiceDispatcher#InnerConnection
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); } } }
InnerConnection的connected方法调用ServiceDispatcher的connected方法。
LoadedApk#ServiceDispatcher#connected
public void connected(ComponentName name, IBinder service) { if (mActivityThread != null) { mActivityThread.post(new RunConnection(name, service, 0)); } else { doConnected(name, service); } }
ServiceDispatcher的mActivityThread是ActivityThread中的Handler H。如此,RunConnection就可以经由H的post方法从而运行在主线程中,因此客户端的ServiceConnection中的方法是在主线程被回调的。
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; }
显然,RunConnection的润方法也是简单的调用了ServiceDispatcher的doConnected方法,由于ServiceDispatcher内部保存了客户端的ServiceConnection对象,因此它可以很方便地调用ServiceConnection对象的onServiceConnected方法。
LoadedApk#ServiceDispatcher#doConnected
public void doConnected(ComponentName name, IBinder service) { ServiceDispatcher.ConnectionInfo old; ServiceDispatcher.ConnectionInfo info; synchronized (this) { if (mForgotten) { // We unbound before receiving the connection; ignore // any connection received. return; } old = mActiveConnections.get(name); if (old != null && old.binder == service) { // Huh, already have this one. Oh well! return; } if (service != null) { // A new service is being connected... set it all up. mDied = false; info = new ConnectionInfo(); info.binder = service; info.deathMonitor = new DeathMonitor(name, service); try { service.linkToDeath(info.deathMonitor, 0); mActiveConnections.put(name, info); } catch (RemoteException e) { // This service was dead before we got it... just // don't do anything with it. mActiveConnections.remove(name); return; } } else { // The named service is being disconnected... clean up. mActiveConnections.remove(name); } if (old != null) { old.binder.unlinkToDeath(old.deathMonitor, 0); } } // 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); } }
客户端的onServiceConnected方法执行后,Service的绑定过程也就完成了。
相关文章推荐
- 向数组中插入元素
- mymemcpy的实现
- Cluster vs Clustering
- 视频格式转换方法之264、avi、YUV420P
- Java垃圾收集算法与内存泄露
- 链表和二叉树
- LinearLayout之初级学习 (二) ScrollView
- LintCode:最长回文子串
- MyBatis级联探讨第一篇——概念和模型
- 做企业永远不变的是做好产品与做好自已
- RxJava学习笔记
- Windows2012配置SQLServer2014AlwaysOn的图解
- Centos7系统下的磁盘挂载
- UNPv1第二十一章:带外数据
- [No000084]C# 使用Log4Net(1)-快速建立一个demo
- 了解这23种设计模式
- SharePoint 2013 Microsoft.Office.Server.UserProfiles.LMTRepopulationJob
- String和StringBuffer的区别
- 检查浏览器视口大小
- 欢迎使用CSDN-markdown编辑器