一、概览
这次继续分析 startService()
的启动过程。 相比于activity,服务可提供在后台长时间的运行操作,同时没有界面。即使切换到后台,服务仍然在后台继续运行。
1.1 服务的三种类型
前台服务 后台服务 绑定服务
1.2 服务的生命周期
service的生命周期如下:
1.3 startService 和 bindService的区别
生命周期区别已经在上面的生命周期图中展示了出来。前者用来做长时间的单一工作,启动后独自运行。后者适合需要多次调用接口的RPC交互场景,偏重于交互。
虽然区分了两种方式,但是一个service可以支持在启动的情况下,再对其进行绑定操作。也就是说, 同时支持两种方式运行
。
1.4 系统服务提供的子类
service IntentService
1.5 服务与线程的选择
服务一般适用于 长时间后台工作
,如网络事务、播放音乐、文件I/O等。线程适合执行耗时操作。如:服务跟随组件如activity的生命周期,那么选择线程即可。
Activity 继承了 ContextWrapper:
二、App端 startService()
2.1 ContextImpl.startService()
ContextWrapper.java
@Override public ComponentName startService(Intent service) { return mBase.startService(service); } // 前台服务 @Override public ComponentName startForegroundService(Intent service) { return mBase.startForegroundService(service); }
ContextWrapper内部有代理了 ContextImpl
,所以我们看看 ContextImpl的 startService():
2.2 ContextImpl.startService()
ContextImpl.java
@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser); } @Override public ComponentName startForegroundService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, true, mUser); }
2.2.1 startServiceCommon()
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); // 直接调用 AMS的 startService方法 , 返回一个 ComponentName 对象。 ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, 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()); } else if (cn.getPackageName().equals("?")) { throw new IllegalStateException( "Not allowed to start service " + service + ": " + cn.getClassName()); } } return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
直接调用 AMS的
startService方法 , 返回一个 ComponentName 对象。
三、AMS 端 startService
3.1 startService()
ActivityManagerService.java
@Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException { // requireForeground 是否是前台服务 enforceNotIsolatedCaller("startService"); ... if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground); synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { // 调用 startServiceLocked res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }
调用 ActiveServices的 startServiceLocked()。
allowBackgroundActivityStarts属性传入false
,再内部继续调用同名的方法startServiceLocked():
3.2 ActiveServices.startServiceLocked()
ActiveServices.java
ActiveServices
是系统用来管理服务的类。内部有一系列的集合list,用来存储ServiceRecord 对象。 也就是系统所有的service都由 ActiveServices 来管理。
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { // fgRequired 是否是前台服务 // allowBackgroundActivityStarts 为false。 final boolean callerFg; // 获取当前进程对象 ProcessRecord if (caller != null) { final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (callerApp == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting service " + service); } callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND; } else { callerFg = true; } // 内部通过PMS解析得到 serviceRecord 对象信息 ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false, false); if (res == null) { return null; } if (res.record == null) { return new ComponentName("!", res.permission != null ? res.permission : "private to package"); } ServiceRecord r = res.record; // ... // 继续启动服务 ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); return cmp; }
retrieveServiceLocked()方法内部最终通过PMS来解析得到 ServiceRecord对象,返回ServiceLookupResult。 ServiceLookupResult
内部封装了 ServiceRecord
对象。
3.2.1 startServiceInnerLocked()
ActiveServices.java
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean ca