Service的启动过程

基于Android U

ContextImpl到AMS的调用过程

要启动Service,我们会调用startService()方法,它在ContextWrapper中实现。

1
2
3
4
frameworks/base/core/java/android/content/ContextWrapper.java
public @Nullable ComponentName startService(Intent service) {
return mBase.startService(service);
}

mBase指的是ContextImpl,Activity的attach()方法中将ContextImpl赋值给ContextWrapper的成员变量mBase。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
frameworks/base/core/java/android/app/ContextImpl.java
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
getOpPackageName(), getAttributionTag(), user.getIdentifier()); // 1
...
return cn;
} catch (RemoteException e) {
...
}
}

在startService()方法中会返回startServiceCommon()方法,在startServiceCommon()方法中会在注释1处调用AMS的代理IActivityManager的startService()方法,最终调用的是AMS的startService()方法。

ActivityThread启动Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
private ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage,
String callingFeatureId, int userId, boolean isSdkSandboxService,
int sdkSandboxClientAppUid, String sdkSandboxClientAppPackage, String instanceName)
throws TransactionTooLargeException {
...
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
...
synchronized (this) {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, callingFeatureId, userId,
isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
instanceName); // 1
}
} finally {
...
}
return res;
}

注释1处调用mServices的startServiceLocked()方法,mServices的类型是ActiveServices。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired,
String callingPackage, @Nullable String callingFeatureId, final int userId,
BackgroundStartPrivileges backgroundStartPrivileges, boolean isSdkSandboxService,
int sdkSandboxClientAppUid, String sdkSandboxClientAppPackage, String instanceName)
throws TransactionTooLargeException {
...

ServiceLookupResult res = retrieveServiceLocked(service, instanceName, isSdkSandboxService,
sdkSandboxClientAppUid, sdkSandboxClientAppPackage, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false, null, false); // 1
...
ServiceRecord r = res.record; // 2
...
final ComponentName realResult =
startServiceInnerLocked(r, service, callingUid, callingPid,
callingProcessName, callingProcessState,
fgRequired, callerFg,
backgroundStartPrivileges, callingPackage); // 3
if (res.aliasComponent != null
&& !realResult.getPackageName().startsWith("!")
&& !realResult.getPackageName().startsWith("?")) {
return res.aliasComponent;
} else {
return realResult;
}
}

注释1处的retrieveServiceLocked()方法会查找是否有与参数service对应的ServiceRecord,如果没有找到,就会调用PackageManagerService去获取参数service对应的Service信息,并封装到ServiceRecord中,最后将ServiceRecord封装为ServiceLookupResult返回。其中ServiceRecord用于描述一个Service,和ActivityRecord类似。

在注释2处通过注释1处返回的ServiceLookupResult得到参数service对应的ServiceRecord,并传入到注释3处的startServiceInnerLocked()方法中。

1
2
3
4
5
6
7
8
9
10
11
12
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service,
int callingUid, int callingPid, String callingProcessName,
int callingProcessState, boolean fgRequired, boolean callerFg,
BackgroundStartPrivileges backgroundStartPrivileges, String callingPackage)
throws TransactionTooLargeException {
...
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting,
callingUid, callingProcessName, callingProcessState,
wasStartRequested, callingPackage);
return cmp;
}

继续调用startServiceInnerLocked()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting, int callingUid, String callingProcessName,
int callingProcessState, boolean wasStartRequested, String callingPackage)
throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg,
false /* whileRestarting */,
false /* permissionsReviewRequired */,
false /* packageFrozen */,
true /* enqueueOomAdj */); // 1
...
if (error != null) {
return new ComponentName("!!", error);
}
...
return r.name;
}

注释1处调用了bringUpServiceLocked()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
boolean enqueueOomAdj)
throws TransactionTooLargeException {
try {
...
return bringUpServiceInnerLocked(r, intentFlags, execInFg, whileRestarting,
permissionsReviewRequired, packageFrozen, enqueueOomAdj);
} finally {
...
}
}

调用bringUpServiceInnerLocked()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private String bringUpServiceInnerLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
boolean enqueueOomAdj)
throws TransactionTooLargeException {
...
final String procName = r.processName; // 1
...
ProcessRecord app;

if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid); // 2
...
if (app != null) {
final IApplicationThread thread = app.getThread();
final int pid = app.getPid();
final UidRecord uidRecord = app.getUidRecord();
if (thread != null) { // 3
try {
...
realStartServiceLocked(r, app, thread, pid, uidRecord, execInFg,
enqueueOomAdj); // 4
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
}
} else {
...
}


if (app == null && !permissionsReviewRequired && !packageFrozen) { // 5
if (r.isSdkSandbox) {
...
} else {
app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated); // 6
}
...
}
...
return null;
}

注释1处得到ServiceRecord的processName值并赋给procName,其中processName用来描述Service想要在哪个进程中运行,默认是当前进程,我们也可以在AndroidManifest.xml文件中设置android:process属性来新开启一个进程运行Service。

在注释2处将procName和Service的uid传入到AMS的getProcessRecordLocked()方法中,查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来描述运行的应用程序进程的信息。

在注释5处判断Service对应的app为null则说明用来运行Service的应用程序进程不存在,则调用注释6处的AMS的startProcessLocked()方法来创建对应的应用程序进程。

这里只讨论没有设置android:process属性,即应用程序进程存在的情况。在注释3处判断如果用来运行Service的应用程序进程存在,则调用注释4处的realStartServiceLocked()方法来启动Service。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
boolean enqueueOomAdj) throws RemoteException {
...
try {
...
thread.scheduleCreateService(r, r.serviceInfo,
null /* compatInfo (unused but need to keep method signature) */,
app.mState.getReportedProcState());
...
} catch (DeadObjectException e) {
...
} finally {
...
}
...
}

在realStartServiceLocked()中调用了thread的scheduleCreateService()方法。其中thread是IApplicationThread类型的,它的实现是ActivityThread的内部类ApplicationThread。

1
2
3
4
5
6
7
8
9
10
frameworks/base/core/java/android/app/ActivityThread$ApplicationThread
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;

sendMessage(H.CREATE_SERVICE, s);
}

scheduleCreateService()方法将启动Service的参数封装成CreateServiceData,sendMessage()方法向H类发送类型为CREATE_SERVICE的消息,并将CreateServiceData传递过去。sendMessage()方法有多个重载方法,最终调用的sendMessage()方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
frameworks/base/core/java/android/app/ActivityThread.java
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
...
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}

这里的mH指的是H,它是ActivityThread的内部类并继承自Handler,是应用程序进程中主线程的消息管理类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
frameworks/base/core/java/android/app/ActivityThread.java
class H extends Handler {
public void handleMessage(Message msg) {
...
switch (msg.what) {
...
case CREATE_SERVICE:
...
handleCreateService((CreateServiceData)msg.obj);
...
break;
...
}
...
}
}

handleMessage()方法根据消息类型为CREATE_SERVICE,会调用handleCreateService()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
frameworks/base/core/java/android/app/ActivityThread.java
private void handleCreateService(CreateServiceData data) {
...
final LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo); // 1
Service service = null;
try {
...
final java.lang.ClassLoader cl;
// 2
if (data.info.splitName != null) {
cl = packageInfo.getSplitClassLoader(data.info.splitName);
} else {
cl = packageInfo.getClassLoader();
}
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent); // 3
ContextImpl context = ContextImpl.getImpl(service
.createServiceBaseContext(this, packageInfo)); // 4
if (data.info.splitName != null) {
context = (ContextImpl) context.createContextForSplit(data.info.splitName);
}
if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
final String attributionTag = data.info.attributionTags[0];
context = (ContextImpl) context.createAttributionContext(attributionTag);
}
// Service resources must be initialized with the same loaders as the application
// context.
context.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));

context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService()); // 5
if (!service.isUiContext()) { // WindowProviderService is a UI Context.
VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class);
if (mLastReportedDeviceId == Context.DEVICE_ID_DEFAULT
|| vdm.isValidVirtualDeviceId(mLastReportedDeviceId)) {
service.updateDeviceId(mLastReportedDeviceId);
}
}
service.onCreate(); // 6
mServicesData.put(data.token, data);
mServices.put(data.token, service); // 7
...
} catch (Exception e) {
...
}
}

注释1处获取要启动Service的应用程序的LoadedApk,LoadedApk是一个APK文件的描述类;

注释2处获取类加载器;

注释3处根据CreateServiceData对象中存储的Service信息,创建Service实例;

注释4处创建Service的上下文环境ContextImpl对象;

注释5处通过Service的attach()方法来初始化Service;

注释6处调用Service的onCreate()方法,这样Service就启动了;

注释7处将启动的Service加入到ActivityThread的成员变量mServices中,其中mService是ArrayMap类型。


Service的启动过程
https://citrus-maxima.github.io/2024/03/10/Service的启动过程/
作者
柚子树
发布于
2024年3月10日
许可协议