Android(安卓)Service的启动流程源码分析(8.0)
16lz
2021-01-24
一,写在前面
在Android中服务有两种状态,一种是启动服务,一种是绑定服务,它们有着不同的生命周期。启动服务的生命周期:onCreate,onStart,onDestroy;绑定服务的生命周期:onCreate,onBind,onUnBind,onDestroy。至于服务具体如何使用,本篇将不做介绍。主要介绍从源码角度,解析启动服务过程。需要注意的是,阅读本篇文章之前建议先了解Activity的启动流程,可参考博客 Android Activity的启动流程源码解析 。二,进入主题
通常需要在Activity组件中启动一个服务,用于在后台执行一些计算的操作。这时,会调用startService(Intent service)方法,其实这个方法的具体实现在Activity的父类ContextWrapper类中,类ContextWrapper是Context的子类。好了,查看源码开始分析吧~ 查看ContextWrapper$startService源码: @Override public ComponentName startService(Intent service) { return mBase.startService(service); }
第3行,字段mBase是Context类型,但Context是一个抽象类,事实上mBase变量是一个ContextImpl对象。给mBase变量设置值是在Activity$attach方法被调用时完成,具体分析见文章 Android Activity的启动流程源码解析 ,这里不再重复阐述。 查看ContextImpl$startService方法源码:
@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser); }//继续查看 private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { //...codeComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier());//...code }
第13行,ActivityManager.getService()返回的是一个IActivityManager的一个代理对象,利用AIDL技术完成进程间通信,需要找到那个extends IActivityManager.Stub的实现类,它就是ActivityManagerService。IActivityManager的代理对象调用startService方法,会向系统服务ActivityManagerService发送一个请求,基于Binder机制,会调用ActivityManagerService$startService方法。详细的代码流程分析见文章 Android Activity的启动流程源码解析 ,这里不再重复阐述。 查看ActivityManagerService$startService方法源码:
@Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException {//...code synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }
第14行,变量mServices是ActiveServices类型的对象。于是,启动服务的工作交给了ActiveServices来处理。 查看ActiveServices源码如下: ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException { //...code ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false); //...code ServiceRecord r = res.record; //...code r.lastActivity = SystemClock.uptimeMillis(); r.startRequested = true; r.delayedStop = false; r.fgRequired = fgRequired; r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), service, neededGrants, callingUid)); //...code ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); return cmp; } //继续查看 ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { //... String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); //... } //继续查看 private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { //... realStartServiceLocked(r, app, execInFg); //... } //继续查看 private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { //... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); //... sendServiceArgsLocked(r, execInFg, true); }
第13行,ServiceRecord封装了要启动的服务一些信息,r作为方法的参数进行传递。 第62行,app.thread是一个IApplicationThread的代理对象,最终会调用ApplicationThread$scheduleCreateService方法启动服务,具体分析可以参考文章 Android Activity的启动流程源码解析 。内部会调用Service$onCreate方法启动服务,后面会有所分析。 第68行,内部会调用onStartCommand方法,这里不做过多介绍,代码流程与onCreate类似。 三,启动服务的操作,交给ActivityThread来处理
继续app.thread.scheduleCreateService进行分析,值得一提的是,ApplicationThread是ActivityThread的内部类。 查看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);}
查看ActivityThread$sendMessage源码如下:
private void sendMessage(int what, Object obj) { sendMessage(what, obj, 0, 0, false);}//继续查看private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { 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; if (async) { msg.setAsynchronous(true); } mH.sendMessage(msg);}
第19行,Handler发送了一个消息,于是启动服务的操作在消息的处理中了。 查看ActivityThread$handleMessage方法源码: public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { //...code case CREATE_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj))); handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; //...code} }
第9行,调用handleCreateService方法启动服务。可以发现,启动服务的过程与启动Activity的过程有相同地方,刚开始将启动组件的操作交给系统服务ActivityManagerService来出来,然后,将启动组件的操作交给ApplicationThread来处理。值得一提是,这两步都涉及到进程间的通信,且是基于Binder机制,可以看到Binder机制在framework层的利用无处不在。最后,处理组件的操作都是通过发送一次消息来完成,启动服务与启动Activity具体做的操作比较相同,这也是为何文章开头建议先了解Activity的启动流程。 继续查看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; Application app = null; try { app = packageInfo.makeApplication(false, mInstrumentation); java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = instantiate(cl, data.info.name, data.intent, app, Application::instantiateService); } 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); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); service.onCreate(); mServices.put(data.token, service); try { ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } }
仔细分析代码可以发现,启动服务最终调用了Activity$handleCreateService方法,与启动Activity最终调用了ActivityThread$performLaunchActivity方法做的事情有些类似,详情参考文章 Android Activity的启动流程源码解析 。 handleCreateService启动服务大致有操作: 第11行,创建Application对象,若应用程序已经存在该对象,则不再创建。 第13行,通过类加载器ClassLoader创建Service的实例。 第26行,创建Service的上下文环境,也就是创建ContextImpl对象,会作为Service$attach方法的参数传入。 第29行,调用Service$attach方法,做初始化一些变量的操作。 第31行,调用Service$onCreate方法启动服务。 第32行,将Service的实例对象存入Map集合中,执行Service生命周期的其他方法时,可以在该集合中取出Service实例。 上述操作,与启动Activity的流程大体类似,每一步操作不再作细致分析,详细分析可以参考文章 Android Activity的启动流程源码解析 。 四,最后
可以发现,启动服务与启动Activity的流程有很多类似之处,了解Activity的启动流程,对于本篇的理解很有意义~ ^_^更多相关文章
- Android(安卓)SQLite总结[转载]
- android 设定activity的进入和退出效果
- Cordova插件编写流程(Android平台)
- Android之service一些基础回顾
- Android(安卓)多分包,方法数超出 65536 限制
- android之多线程工作(一)AsyncTask .
- 在Android(安卓)10.0中Activity的启动流程
- [每天学点Android开发]Building Web Apps in WebView
- Android(安卓)Touch事件分析