前面分析了Activity的启动流程,下面开始分析Service的启动,本文分析的是startService的流程,android的版本为4.1.2
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
这就是startService
的入口,mUser
就是代表当前的用户,在后面启动Serivce的流程中,会通过此实例获取用户的uid。
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
......
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 e.rethrowFromSystemServer();
}
接下来通过binder通信,Service启动流程会进入ActivityManagerService的startService函数中。
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType) {
......
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = startServiceLocked(caller, service,
resolvedType, callingPid, callingUid);
Binder.restoreCallingIdentity(origId);
return res;
}
}
接下来会调用startServiceLocked
。startServiceLocked
的逻辑稍微显得复杂一些,主要的难点是获取Service信息。
ComponentName startServiceLocked(IApplicationThread caller,
Intent service, String resolvedType,
int callingPid, int callingUid) {
synchronized(this) {
......
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
callingPid, callingUid);
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record;
//检测当前用户是否有权限访问Intent中的Data和ClipData
int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service);
//将即将启动的Service从等待启动列表中删除
if (unscheduleServiceRestartLocked(r)) {
if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
}
......
if (!bringUpServiceLocked(r, service.getFlags(), false)) {
return new ComponentName("!", "Service process is bad");
}
return r.name;
}
}
系统首先调用retriveServiceLocked
函数获取即将要启动的Service信息,并封装成ServiceLookupResult
对象,ServiceLoopupResult
对象内部包括了一个ServiceRecord
对象和记录Service权限的字符串,retrivveServiceLocked
函数的执行过程会在后面分析。获得ServiceLookupResult结果res后会进行判断,如果未找到即将启动的Service的ServiceLookupResult对象,则直接返回;接下来会将即将启动的Service从等待启动列表中删除,最终会调用会进入bringupServiceLocked
,bringupServiceLocked
函数中包含了ActivityManagerService对Service进行不同配置以及系统处于不同状态的不同启动方式。
private final boolean bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean whileRestarting) {
//Slog.i(TAG, "Bring up service:");
//r.dump(" ");
//Service已经运行,则执行Service的onStartCommand函数
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, false);
return true;
}
//如果正在等待重启,则直接返回
if (!whileRestarting && r.restartDelay > 0) {
// If waiting for a restart, then do nothing.
return true;
}
//从正在重启的服务列表中删除即将启动的服务
mRestartingServices.remove(r);
//服务正在启动,当前应用不能被停止
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.packageName, false, r.userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.packageName + ": " + e);
}
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String appName = r.processName;
ProcessRecord app;
//如果Service不需要运行在单独的进程
if (!isolated) {
//尝试获取Service的进程
app = getProcessRecordLocked(appName, r.appInfo.uid);
if (DEBUG_MU)
Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
//如果Service所在进程已经启动,但是Service还未启动,则去执行realStartServiceLocked,在进程内执行Service的启动流程
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName);
realStartServiceLocked(r, app);
return true;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, 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;
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
//Service所在的进程未启动,则启动进程
if (app == null) {
//如果Service所在进程并没有被启动,则根据Service信息去启动一个新的进程,新进程启动完成后则去启动Service
if ((app=startProcessLocked(appName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated)) == null) {
Slog.w(TAG, "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad");
bringDownServiceLocked(r, true);
return false;
}
if (isolated) {
r.isolatedProc = app;
}
}
//将即将启动的Service添加到pending队列中
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
return true;
}
这部分的代码描述了调用startService
时可能遇到的三种情况:
- 目标Service已经启动,则去执行
onStartCommand
- 目标Service未启动,但是Service所在的进程已经启动
- 目标Service未启动且Service所在进程未启动,需要新建进程
本篇的分析到此结束,接下来我会分3篇文章分别取分析这三种不同的启动方式。