1. Service概述
Service作为Android四大组件之一,在开发过程中非常常用,它虽然没有ui,但是同样可以在后台做很多重要的事情,我们平时使用启动service主要通过startService以及bindService来启动service以便已经相关操作。本文将介绍startService的原理,后续将分别介绍bindService的原理,以及在Android O上对service的新增限制管控。
注:本文基于Android 8.1
2. Service分类
从启动方式上,可以分别通过startService以及bindService启动,两者之间最重要的区别在于bindService可以建立binder连接,更加方便通信。
从运行方式上,可以分为前台service(foregroundService,下面简称fg-service)与后台service,两者的区别在于有前台service的进程对应的优先级会更高,不容易被系统清理掉,但是前台service需要在通知栏里面显示一个常驻的通知。
3. startService时序图
startService的启动大致分为三种情况:
对应进程不存在(先启动进程然后启动service并执行onCreate和onStartCommand)
进程存在但是service不存在(启动service并执行onCreate和onStartCommand)
进程和service都存在(只执行onStartCommand)
上面的时序图主要针对进程存在,但是service不存在的情况,其他两种在主要流程上没有太大区别,关键在于其中有一些特殊判断,在文章过程中也会提到。
4. 源码解析
4.1 ContextImpl.startService
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
public ComponentName startForegroundService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, true, mUser);
}
// 最终的入口都在这个方法中
// foreground service只是传参requireForeground为true,普通service为false
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
// binder call至ams
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();
}
}
最终通过startServiceCommon调用至ams,注意这里返回值有进行特殊处理,然后抛出了一些异常,主要返回值的component的packageName有"!","!!","?"三种,后面在介绍源码过程中可以看到具体是哪里会返回这些异常。
"!":权限校验没通过,不允许启动
"!!":无法启动
"?":不允许启动
4.2 ActivityManagerService.startService
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// 进行一些简单的校验
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
// callingPackage不能为空
if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
// mService正是ActiveServices对象
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
这块只是简单校验之后,就调用到了ActiveServices.startServiceLocked。
参数解析:
caller:发起startService的进程对应的IApplicationThread对象
service:要启动的service的intent
resolvedType:service类型,启动的时候可以设置data已经schema等
requireForeground:是否发起启动foregroundService
callingPackage:发起startService的进程的packageName
userId:当前用户id
4.3 ActiveServices.startServiceLocked
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
final boolean callerFg;
// 获取发起binder call的caller进程,如果不存在则抛异常
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;
}
// 拿到要启动的service的信息
// 主要是从packageManagerService中查询,然后缓存起来
// 其中还进行了一些权限的校验,4.4小节详细介绍
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
// 没有查到要启动的service,直接return了
if (res == null) {
return null;
}
// 这里就能看到前面提到的返回component的package为“!”的情况了
// 原因是没有对应的servicerecord,没有的原因会在下面4.4小节中进一步介绍
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
// 拿到要启动的serviceRecord,这个就是我们在manifest中注册的service组件对应在系统中封装起来的对象
ServiceRecord r = res.record;
// 判断user是否存在
if (!mAm.mUserController.exists(r.userId)) {
return null;
}
// 是否要启动fg-service
if (!r.startRequested && !fgRequired) {
// 这块是校验如果要启动的service是一个后台service
// 那么需要看是否拥有后台启动的权限,不允许就无法后台启动
final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
r.appInfo.targetSdkVersion, callingPid, false, false);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
// 新升级到O的应用可能会遇到这问题,因为不允许后台情况下的app启动后台service
Slog.w(TAG, "Background start not allowed: service "
+ service + " to " + r.name.flattenToShortString()
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage);
if (allowed == ActivityManager.APP_START_MODE_DELAYED) {
return null;
}
// 不允许启动,此处封装component的packageName为“?”,对应前面提到的,会抛出相关异常
UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);
return new ComponentName("?", "app is in background uid " + uidRec);
}
}
...
// 如果这个service正在调度重启,那么取消重启,因为马上要启动了
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);
}
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));
final ServiceMap smap = getServiceMapLocked(r.userId);
boolean addToStarting = false;
// 如果调用者在后台,且不是启动的前台service,判断是否需要delay
if (!callerFg && !fgRequired && r.app == null
&& mAm.mUserController.hasStartedUserState(r.userId)) {
ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
if (r.delayed) {
return r.name;
}
if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
smap.mDelayedStartList.add(r);
r.delayed = true;
return r.name;
}
addToStarting = true;
} else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
addToStarting = true;
}
}
...
// 准备启动service了
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
小结:
校验caller
拿到serviceRecord,进一步校验
校验是否有可以后台启动
是否需要delay
startServiceInnerLocked
4.4 ActiveServices.retrieveServiceLocked
private ServiceLookupResult retrieveServiceLocked(Intent service,
String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
ServiceRecord r = null;
// 获取user
userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
// 根据userId获取ServiceMap
// 有一个user为key,ServiceMap为v的map,保存了所有的service信息
// 每个user对应一个
// ServiceMap是一个handler对象,用的looper是ActivityManager线程
// 其中主要保存的都是存放service的各map,以不同的方式存储的Servicerecord
ServiceMap smap = getServiceMapLocked(userId);
final ComponentName comp = service.getComponent();
// 通过component从ServiceMap查询
if (comp != null) {
r = smap.mServicesByName.get(comp);
}
...
if (r == null) {
try {
// 如果没能查到,那需要从PackageManager去查询了
ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
resolvedType, ActivityManagerService.STOCK_PM_FLAGS
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
userId, callingUid);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
": not found");
return null;
}
// 封装ComponentName
ComponentName name = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
// FLAG_EXTERNAL_SERVICE类型的service必须有人去bind
// 这块就不贴具体实现了,startService过程中这个逻辑不会走到
...
if (userId > 0) {
if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
sInfo.name, sInfo.flags)
&& mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) {
userId = 0;
smap = getServiceMapLocked(0);
}
sInfo = new ServiceInfo(sInfo);
sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
}
r = smap.mServicesByName.get(name);
// 拿到ServiceRecord,如果没有需要新建
if (r == null && createIfNeeded) {
...
// 这块主要就是ServiceRecord对象创建以及放入ServiceMap中
}
}
}
if (r != null) {
...
// 这块主要是做一些权限校验,包括export(manifest中指定是否允许其他进程启动)
// 以及自己指定的service权限
if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid,
resolvedType, r.appInfo)) {
return null;
}
// 查找成功
return new ServiceLookupResult(r, null);
}
// 没有查找成功返回null
// 上面一节有提到,如果这里返回null则会再进一步返回到ContextImpl中抛出异常
return null;
}
这块做了两件事:
查找ServiceRecord,如果不存在则创建
权限检查
4.5 ActiveServices.startServiceInnerLocked
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
r.callStart = false;
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
// bringUpServiceLocked这个是启动service的核心
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
// 下面主要是进行delay
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
smap.mStartingBackground.add(r);
r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT;
if (first) {
smap.rescheduleDelayedStartsLocked();
}
} else if (callerFg || r.fgRequired) {
smap.ensureNotStartingBackgroundLocked(r);
}
return r.name;
}
这里没做什么事,主要实现都在bringUpServiceLocked
4.6 ActiveServices.bringUpServiceLocked
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
// 从上面的时序图可以知道sendServiceArgsLocked中主要是要调度执行service的onStartCommand
// 这里怎么直接就执行了呢?
// 原因在于判断条件,对于没有执行onCreate的service,r.app是null,所以不会执行这个流程
// 也就是没有启动过的service不会走这里,只有启动过的service才会
// 所以对于已经启动过的service,重复startService只会走onStartCommand,就是因为这里,然后return
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
// 如果不是调度重启,且已经在restart列表中,return
// 只有调度重启的地方调用过来whileRestarting为true
if (!whileRestarting && mRestartingServices.contains(r)) {
return null;
}
// 从restart中移除,因为马上要执行启动了
if (mRestartingServices.remove(r)) {
clearRestartingIfNeededLocked(r);
}
...
// 这中间是一些简单的状态判断,有兴趣可以自己查看源码
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
String hostingType = "service";
ProcessRecord app;
if (!isolated) {
// 进程存在那就直接走真正启动service的逻辑了
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
}
} else {
// isolated进程处理,O上webview进程属于这种类型,加以特殊处理,标记hostingType
// hostingType主要用于启动进程的时候
app = r.isolatedProc;
if (WebViewZygote.isMultiprocessEnabled()
&& r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
hostingType = "webview_service";
}
}
// 进程不存在,那还得先启动进程
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
...
// 因为要启动进程,所以需要记一下这次启动进程的原因是因为需要启动这个service
// 等到进程启动成功之后,在进程attachApplicationLocked的时候会再去启动这个serivice
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
return null;
}
小结:
如果service已经存在那么直接调度sendServiceArgsLocked(将会执行service.onStartCommand)
处理service重启相关数据结构
进程存在,则realStartServiceLocked
进程不存在则先启动进程并把service保存在mPendingServices
4.7 ActiveServices.realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
// 这里主要是计算设置service的timeout
// 因为service的执行是计算在ANR机制中的,这里就是开始计时
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
// 如果是前台service需要更新并记录当前前台serivice的状态
updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
// 更新进程优先级
mAm.updateOomAdjLocked();
boolean created = false;
try {
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
// 设置process的状态为start service
// 这样在更新进程优先级的时候会有对应的处理,其实就是会提升优先级
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
// 到APP的进程中了,执行IApplicationThread.scheduleCreateService
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) {
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
if (newService) {
app.services.remove(r);
r.app = null;
}
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
if (r.whitelistManager) {
app.whitelistManager = true;
}
requestServiceBindingsLocked(r, execInFg);
// 更新绑定的activity,这块主要针对bindService
updateServiceClientActivitiesLocked(app, null, true);
// 如果需要执行service的start则加入到pendingStarts
// r.startRequested在startServiceLocked就标记了
// 且startServiceLocked时就已经加入到pendingStarts
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null, 0));
}
// 这里将会执行service.onStartCommand
sendServiceArgsLocked(r, execInFg, true);
...
// delay相关
}
小结:
开始计算service “create”的ANR计时
调用到app进程创建并执行service的onCreate
sendServiceArgsLocked
4.8 ActiveServices.sendServiceArgsLocked
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
// startServiceLocked时已经加入到pendingStarts
final int N = r.pendingStarts.size();
if (N == 0) {
return;
}
ArrayList<ServiceStartArgs> args = new ArrayList<>();
while (r.pendingStarts.size() > 0) {
ServiceRecord.StartItem si = r.pendingStarts.remove(0);
if (si.intent == null && N > 1) {
continue;
}
si.deliveredTime = SystemClock.uptimeMillis();
r.deliveredStarts.add(si);
si.deliveryCount++;
if (si.neededGrants != null) {
mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
si.getUriPermissionsLocked());
}
mAm.grantEphemeralAccessLocked(r.userId, si.intent,
r.appInfo.uid, UserHandle.getAppId(si.callingId));
// 再次开始ANR的计时,不过此处计时是“start”
bumpServiceExecutingLocked(r, execInFg, "start");
if (!oomAdjusted) {
oomAdjusted = true;
mAm.updateOomAdjLocked(r.app, true);
}
// O上开始,调用startForegroundService需要5s内调用startForeground
// 如果调用startForegroundService就处于r.fgRequired
// 此处是如果发现需要调用startForeground但是没调,则认为超时了
if (r.fgRequired && !r.fgWaiting) {
if (!r.isForeground) {
scheduleServiceForegroundTransitionTimeoutLocked(r);
} else {
r.fgRequired = false;
}
}
int flags = 0;
if (si.deliveryCount > 1) {
flags |= Service.START_FLAG_RETRY;
}
if (si.doneExecutingCount > 0) {
flags |= Service.START_FLAG_REDELIVERY;
}
// 创建ServiceStartArgs
args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
}
ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
slice.setInlineCountLimit(4);
Exception caughtException = null;
try {
// 调度到APP进程执行scheduleServiceArgs(将会执行service.onStartCommand)
r.app.thread.scheduleServiceArgs(r, slice);
} catch (TransactionTooLargeException e) {
scheduleServiceArgs
...
}
// 如果发生了异常需要停掉service
if (caughtException != null) {
final boolean inDestroying = mDestroyingServices.contains(r);
for (int i = 0; i < args.size(); i++) {
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
}
if (caughtException instanceof TransactionTooLargeException) {
throw (TransactionTooLargeException)caughtException;
}
}
}
小结:
开始service“start”的ANR计时
创建ServiceStartArgs
调度到app进程执行service的onStartCommand
4.9 ActivityThread.handleCreateService
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);
}
public void handleMessage(Message msg) {
switch (msg.what) {
...
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;
...
}
private void handleCreateService(CreateServiceData data) {
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 {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
// 创建application
Application app = packageInfo.makeApplication(false, mInstrumentation);
// 执行service attach
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 执行service的onCreate
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);
}
}
}
app进程中binder线程调度过来之后,发送消息到主线程执行handleCreateService,在handleCreateService中终于看到了我们熟悉的onCreate了
处理完了service的生命周期,还要告诉ams,我处理完了,因为那边还在进行service的ANR计时呢
4.10 ActivityThread.handleServiceArgs
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) {
// 执行service的onStartCommand方法
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
// 这里在前面讲解SharedPreferences的时候有提到,是在等待sp的任务写入完成
QueuedWork.waitToFinish();
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
ensureJitEnabled();
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to start service " + s
+ " with " + data.args + ": " + e.toString(), e);
}
}
}
}
scheduleServiceArgs中同样是发送消息到app主线程然后执行scheduleServiceArgs
scheduleServiceArgs中执行service.onStartCommand,然后告诉AMS执行完毕
4.11 ActivityManagerService.serviceDoneExecuting
public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);
throw new IllegalArgumentException("Invalid service token");
}
// ActiveSercices.serviceDoneExecutingLocked
mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
}
}
4.12 ActiveServices.serviceDoneExecutingLocked
void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
boolean inDestroying = mDestroyingServices.contains(r);
if (r != null) {
if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {
r.callStart = true;
// 这里的res是onStartCommand的返回值
switch (res) {
case Service.START_STICKY_COMPATIBILITY:
case Service.START_STICKY: {
r.findDeliveredStart(startId, true);
r.stopIfKilled = false;
break;
}
case Service.START_NOT_STICKY: {
r.findDeliveredStart(startId, true);
if (r.getLastStartId() == startId) {
r.stopIfKilled = true;
}
break;
}
case Service.START_REDELIVER_INTENT: {
ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
if (si != null) {
si.deliveryCount = 0;
si.doneExecutingCount++;
r.stopIfKilled = true;
}
break;
}
case Service.START_TASK_REMOVED_COMPLETE: {
r.findDeliveredStart(startId, true);
break;
}
default:
throw new IllegalArgumentException(
"Unknown service start result: " + res);
}
if (res == Service.START_STICKY_COMPATIBILITY) {
r.callStart = false;
}
} else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
if (!inDestroying) {
if (r.app != null) {
Slog.w(TAG, "Service done with onDestroy, but not inDestroying: "
+ r + ", app=" + r.app);
}
} else if (r.executeNesting != 1) {
Slog.w(TAG, "Service done with onDestroy, but executeNesting="
+ r.executeNesting + ": " + r);
r.executeNesting = 1;
}
}
final long origId = Binder.clearCallingIdentity();
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
Binder.restoreCallingIdentity(origId);
} else {
Slog.w(TAG, "Done executing unknown service from pid "
+ Binder.getCallingPid());
}
}
其中的res处理:
如果是START_STICKY_COMPATIBILITY或者START_STICKY那么如果进程挂掉了,service依旧会重启,很多app会利用这个进行保活。
在其中的serviceDoneExecutingLocked会把前面的计时消息给remove掉,如果service的生命周期在规定时间内执行完毕,就不会ANR了。
总结
startService过程中如果进程不存在会创建进程
service不存在时默认情况下会先执行service的onCreate,再执行service的onStartCommand
service存在时只会执行service的onStartCommand
service的onCreate和onStartCommand都会被ANR计时监控,规定时间内没有处理完就会超时
onStartCommand处理之后还要等待sp写入完毕才会返回ams,所以不适合在onStartCommand中做大量的sp操作,即使是用的是apply异步进行
onStartCommand的返回值可以控制service是否在进程被kill之后依旧重启service
来源:oschina
链接:https://my.oschina.net/u/920274/blog/3064466