一、概览
上篇学习了activity
的启动流程,这次继续分析startService()
的启动过程。 相比于activity,服务可提供在后台长时间的运行操作,同时没有界面。即使切换到后台,服务仍然在后台继续运行。
1.1 服务的三种类型
-
前台服务
无界面,必须设置通知栏(5s内,如果没有调用startForground()则会抛出ANR)。用户能够直接感知、注意到的操作,如 使用音频播放 -
后台服务
无界面,用户不会直接注意到的操作。 -
绑定服务
无界面。处于绑定的状态(类似C/S架构),此时组件可以与服务进行交互,如:RPC的调用,必须要unbind来解绑,服务才会终止。一个服务可绑定多个组件,只要有一个组件bind服务,服务就处于绑定状态。只有当所有绑定组件都unbind后,服务才会被销毁。
1.2 服务的生命周期
service的生命周期如下:
1.3 startService 和 bindService的区别
生命周期区别已经在上面的生命周期图中展示了出来。前者用来做长时间的单一工作,启动后独自运行。后者适合需要多次调用接口的RPC交互场景,偏重于交互。
虽然区分了两种方式,但是一个service可以支持在启动的情况下,再对其进行绑定操作。也就是说,同时支持两种方式运行
。
1.4 系统服务提供的子类
service
直接继承service,从写onCreate(),以及其他可选生命周期回调方法。所有回调默认运行在主线程IntentService
内部封装了 handlerThread 对象,把所有的生命周期回调切换到子线程。
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 callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
}
r.callStart = false;
StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(),
r.name.getClassName(), StatsLog.SERVICE_STATE_CHANGED__STATE__START);
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
// 继续调用
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
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;
}
3.2.2 bringUpServiceLocked()
ActiveServices.java
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
if (r.app != null && r.app.thread != null) {
// 1 调用 service.onStartCommand()
sendServiceArgsLocked(r, execInFg, false);
return null;
}
if (!whileRestarting && mRestartingServices.contains(r)) {
// If waiting for a restart, then do nothing.
return null;
}
//...
// We are now bringing the service up, so no longer in the
// restarting state.
if (mRestartingServices.remove(r)) {
clearRestartingIfNeededLocked(r);
}
// Make sure this service is no longer considered delayed, we are starting it now.
if (r.delayed) {
getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
// Make sure that the user who owns this service is started. If not,
// we don't want to allow it to run.
if (!mAm.mUserController.hasStartedUserState(r.userId)) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": user " + r.userId + " is stopped";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
//....
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
ProcessRecord app;
// 是否在单独的进程 不在独立进程
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
// 如果进程已经启动
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
// 启动服务
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, 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 (WebViewZygote.isMultiprocessEnabled()
&& r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
hostingRecord = HostingRecord.byWebviewZygote(r.instanceName);
}
if ((r.serviceInfo.flags & ServiceInfo.FLAG_USE_APP_ZYGOTE) != 0) {
hostingRecord = HostingRecord.byAppZygote(r.instanceName, r.definingPackageName,
r.definingUid);
}
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {
//如果进程没有启动,那么开启进程,等进程拉起后,会调用AMS.attacthApplication(),再次调用 ActiveServices.attachApplicationLocked(),内部再次调用 realStartServiceLocked()
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, 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;
}
}
if (r.fgRequired) {
mAm.tempWhitelistUidLocked(r.appInfo.uid,
SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch");
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
stopServiceLocked(r);
}
}
return null;
}
- 服务如果已经启动过了,则调用 service.onStartCommand()
如果进程存在
,则直接调用 realStartServiceLocked() 启动服务如果进程不存在
,那么久拉起进程。等进程拉起后,会调用AMS.attacthApplication(),内部调用 ActiveServices.attachApplicationLocked(),内部再次调用 realStartServiceLocked()
因此,我们继续看 realStartServiceLocked():
3.2.3 realStartServiceLocked()
/Users/avengong/Library/Android/sdk/sources/android-29/com/android/server/am/ActiveServices.java
注意: 不要被startService开头的方法名字迷惑了。这里的start意思是 拉起app端的service 实例。bindService()启动方式也会调用到这里。
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
....
r.setProcess(app);
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
// 发送ANR 检测消息
bumpServiceExecutingLocked(r, execInFg, "create");
// 更新AMS中的 processRecord Lru集合
mAm.updateLruProcessLocked(app, false, null);
updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
boolean created = false;
try {
...
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
// 执行 服务的onCreate() 流程
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
r.postNotification();
// 至此,表示系统侧的 service 创建完毕。
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.setProcess(null);
}
// Retry. 如果没有启动,会再次尝试
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
if (r.whitelistManager) {
app.whitelistManager = true;
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
if (newService && created) {
app.addBoundClientUidsOfNewService(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, 0));
}
// 回调onStartCommand()方法
sendServiceArgsLocked(r, execInFg, true);
if (r.delayed) {
getServiceMapLocked(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) {
stopServiceLocked(r);
}
}
}
- 发送ANR延迟检测消息
- 执行onCreate()流程,回调App端 scheduleCreateService()
- 执行onStartCommand()流程
3.2.4 bumpServiceExecutingLocked(r, execInFg, "create")
ActiveServices.java
private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
// ...
boolean timeoutNeeded = true;
if ((mAm.mBootPhase < SystemService.PHASE_THIRD_PARTY_APPS_CAN_START)
&& (r.app != null) && (r.app.pid == android.os.Process.myPid())) {
timeoutNeeded = false;
}
long now = SystemClock.uptimeMillis();
if (r.executeNesting == 0) {
r.executeFg = fg;
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
}
if (r.app != null) {
r.app.executingServices.add(r);
r.app.execServicesFg |= fg;
if (timeoutNeeded && r.app.executingServices.size() == 1) {
scheduleServiceTimeoutLocked(r.app);
}
}
} else if (r.app != null && fg && !r.app.execServicesFg) {
r.app.execServicesFg = true;
// 发送超时ANR检测消息
if (timeoutNeeded) {
scheduleServiceTimeoutLocked(r.app);
}
}
r.executeFg |= fg;
r.executeNesting++;
r.executingStart = now;
}
3.2.5 ActiveServices.scheduleServiceTimeoutLocked()
ActiveServices.java
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
if (proc.executingServices.size() == 0 || proc.thread == null) {
return;
}
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
mAm.mHandler.sendMessageDelayed(msg,
proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}
- 如果超时还没有移除这个消息,那么就判定为启动service ANR了,执行SERVICE_TIMEOUT_MSG消息逻辑,内部会调用ActiveServices.serviceTimeout() 方法。
- 前台服务超时时间:SERVICE_TIMEOUT=10s
- 后天服务超时时间:200s
3.2.6 ActiveServices.serviceTimeout()
ActiveServices.java
void serviceTimeout(ProcessRecord proc) {
String anrMessage = null;
synchronized(mAm) {
...
final long now = SystemClock.uptimeMillis();
final long maxTime = now -
(proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
ServiceRecord timeout = null;
long nextTime = 0;
for (int i=proc.executingServices.size()-1; i>=0; i--) {
ServiceRecord sr = proc.executingServices.valueAt(i);
if (sr.executingStart < maxTime) {
timeout = sr;
break;
}
if (sr.executingStart > nextTime) {
nextTime = sr.executingStart;
}
}
if (timeout != null && mAm.mProcessList.mLruProcesses.contains(proc)) {
Slog.w(TAG, "Timeout executing service: " + timeout);
StringWriter sw = new StringWriter();
PrintWriter pw = new FastPrintWriter(sw, false, 1024);
pw.println(timeout);
timeout.dump(pw, " ");
pw.close();
mLastAnrDump = sw.toString();
mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);
mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);
anrMessage = "executing service " + timeout.shortInstanceName;
} else {
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
mAm.mHandler.sendMessageAtTime(msg, proc.execServicesFg
? (nextTime+SERVICE_TIMEOUT) : (nextTime + SERVICE_BACKGROUND_TIMEOUT));
}
}
// 直接执行app的 ANR 流程
if (anrMessage != null) {
proc.appNotResponding(null, null, null, null, false, anrMessage);
}
}
如果发生ANR,则直接执行app的 ANR 流程,具体怎么执行后续再分析~
疑问,既然发送了ANR判定消息,那么什么时候去移除这个消息呢?
答:在app端创建完service后,会再次告知AMS端执行完成。 这里先看app端如何处理。
四、App 端 scheduleCreateService()
AMS通过Binder跨进程调用到app端,接收的对象为 ActivityThread的静态内部类 ApplicationThread
。我们先看onCreate()执行流程。
4.1 ApplicationThread.scheduleCreateService
ActivityThread.java
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);
}
- IBinder token: 对应 ServiceRecord
- ServiceInfo info:服务信息
- CompatibilityInfo compatInfo:
- int processState:进程状态
发送了CREATE_SERVICE
一个消息到主线程。
4.2 H.CREATE_SERVICE 消息
ActivityThread.java
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;
4.3 ActivityThread.handleCreateService()
ActivityThread.java
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 表示已安装的apk的所有信息
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
/// 反射 service实例
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
}
//...
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
// 创建service 的context 对象
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
// attach app信息到service
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 调用 service的 onCreate()方法
service.onCreate();
// 把token作为key,存入到 mServices map中
mServices.put(data.token, service);
try {
// 告知 AMS service已经启动完毕
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);
}
}
}
- 通过
反射创建 service
实例对象 - 创建context,并且attach到service
- 调用service的onCreate()方法
- 调用
serviceDoneExecuting()
通知AMS,service已经启动完毕,注意传入的是SERVICE_DONE_EXECUTING_ANON = 0
五、AMS端 serviceDoneExecuting()
ActivityManagerService.java
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");
}
mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
}
}
调用了 ActiveServices 的方法:
5.1 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) {
...
} else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {
...
}
final long origId = Binder.clearCallingIdentity();
// 继续调用方法
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
Binder.restoreCallingIdentity(origId);
} else {
Slog.w(TAG, "Done executing unknown service from pid "
+ Binder.getCallingPid());
}
}
5.2 serviceDoneExecutingLocked()
ActiveServices.java
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
boolean finishing) {
r.executeNesting--;
if (r.executeNesting <= 0) {
if (r.app != null) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"Nesting at 0 of " + r.shortInstanceName);
r.app.execServicesFg = false;
r.app.executingServices.remove(r);
if (r.app.executingServices.size() == 0) {
// 移除 ANR超时消息
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
} else if (r.executeFg) {
// Need to re-evaluate whether the app still needs to be in the foreground.
for (int i=r.app.executingServices.size()-1; i>=0; i--) {
if (r.app.executingServices.valueAt(i).executeFg) {
r.app.execServicesFg = true;
break;
}
}
}
if (inDestroying) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"doneExecuting remove destroying " + r);
mDestroyingServices.remove(r);
r.bindings.clear();
}
mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
}
r.executeFg = false;
if (r.tracker != null) {
final int memFactor = mAm.mProcessStats.getMemFactorLocked();
final long now = SystemClock.uptimeMillis();
r.tracker.setExecuting(false, memFactor, now);
r.tracker.setForeground(false, memFactor, now);
if (finishing) {
r.tracker.clearCurrentOwner(r, false);
r.tracker = null;
}
}
if (finishing) {
if (r.app != null && !r.app.isPersistent()) {
r.app.services.remove(r);
r.app.updateBoundClientUids();
if (r.whitelistManager) {
updateWhitelistManagerLocked(r.app);
}
}
r.setProcess(null);
}
}
}
整个流程:
- app端开始发起启动服务请求,发往AMS。
- AMS端执行创建serviceRecord,同时发送一个ANR延迟消息。通知app端可以创建service。
- app端创建service,执行onCreate(),再次通知AMS端,移除ANR消息。
至此,整个onCreate()流程执行完毕
。
还记得在AMS端 3.2.3 小结中的realStartServiceLocked()方法,内部在执行完onCreate()之后,会调用 sendServiceArgsLocked()
来执行 onStartCommand()
方法:
5.3 sendServiceArgsLocked()
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
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 (DEBUG_SERVICE) {
Slog.v(TAG_SERVICE, "Sending arguments to: "
+ r + " " + r.intent + " args=" + si.intent);
}
if (si.intent == null && N > 1) {
// If somehow we got a dummy null intent in the middle,
// then skip it. DO NOT skip a null intent when it is
// the only one in the list -- this is to support the
// onStartCommand(null) case.
continue;
}
si.deliveredTime = SystemClock.uptimeMillis();
r.deliveredStarts.add(si);
si.deliveryCount++;
if (si.neededGrants != null) {
mAm.mUgmInternal.grantUriPermissionUncheckedFromIntent(si.neededGrants,
si.getUriPermissionsLocked());
}
mAm.grantEphemeralAccessLocked(r.userId, si.intent, UserHandle.getAppId(r.appInfo.uid),
UserHandle.getAppId(si.callingId));
bumpServiceExecutingLocked(r, execInFg, "start");
if (!oomAdjusted) {
oomAdjusted = true;
mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
}
if (r.fgRequired && !r.fgWaiting) {
if (!r.isForeground) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "Launched service must call startForeground() within timeout: " + r);
}
scheduleServiceForegroundTransitionTimeoutLocked(r);
} else {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "Service already foreground; no new timeout: " + r);
}
r.fgRequired = false;
}
}
int flags = 0;
if (si.deliveryCount > 1) {
flags |= Service.START_FLAG_RETRY;
}
if (si.doneExecutingCount > 0) {
flags |= Service.START_FLAG_REDELIVERY;
}
args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
}
ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
slice.setInlineCountLimit(4);
Exception caughtException = null;
try {
// 执行 scheduleServiceArgs(),最终调用 onStartCommand()方法。
r.app.thread.scheduleServiceArgs(r, slice);
} catch (TransactionTooLargeException e) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large for " + args.size()
+ " args, first: " + args.get(0).args);
Slog.w(TAG, "Failed delivering service starts", e);
caughtException = e;
} catch (RemoteException e) {
// Remote process gone... we'll let the normal cleanup take care of this.
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while sending args: " + r);
Slog.w(TAG, "Failed delivering service starts", e);
caughtException = e;
} catch (Exception e) {
Slog.w(TAG, "Unexpected exception", e);
caughtException = e;
}
if (caughtException != null) {
// Keep nesting count correct
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;
}
}
}
执行 scheduleServiceArgs()
,最终调用 onStartCommand()方法。
五、App端 scheduleServiceArgs()
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
List<ServiceStartArgs> list = args.getList();
for (int i = 0; i < list.size(); i++) {
ServiceStartArgs ssa = list.get(i);
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = ssa.taskRemoved;
s.startId = ssa.startId;
s.flags = ssa.flags;
s.args = ssa.args;
// 发送消息 SERVICE_ARGS
sendMessage(H.SERVICE_ARGS, s);
}
}
H
收到 SERVICE_ARGS
消息后,会调用 handleServiceArgs()
方法:
5.1 handleServiceArgs() 消息
private void handleServiceArgs(ServiceArgsData data) {
// 从map中获取 service对象
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) {
// 调用 onStartCommand()
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
// 通知AMS start阶段完成
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to start service " + s
+ " with " + data.args + ": " + e.toString(), e);
}
}
}
}
- 调用 onStartCommand() 方法,内部会调用onStart()方法(已废弃)
- 通知AMS,start阶段完成。最终会在AMS端,调用 serviceDoneExecuting(),内部继续调用serviceDoneExecutingLocked(),同之前逻辑一样。
5.1.1 Service.onStartCommand
Service.java
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
//调用onStart() 方法。
onStart(intent, startId);
return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}
onStartCommand()
和onStart()
也都调用了。至此,service
启动完毕。
六、总结
简单总结整个流程:
- app端往AMS端发起启动服务请求
- AMS端执行创建serviceRecord,同时发送一个ANR延迟消息。通知app端可以创建service,接着调用 onStartCommand()方法
- app端创建service,执行onCreate(),再次通知AMS端,移除ANR消息。后续接着处理onStartCommand()方法,再次通知AMS,移除ANR消息。