源码角度分析Service

本文基于aosp8.0源码分析

Service的启动

Service的启动分两种,一种startService,另一种bindService

StartService

一般我们会在Activity中通过startService来启动一个服务

Activity.startService

其内部实际上是由ContextWrapperstartService来启动,实际启动的地方是在ContextImpl.startService

ContextImpl.startService
1
2
3
4
5
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
ContextImpl.startServiceCommon
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
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(), 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();
}
}
  • 这里首选需要验证服务,5.0之后隐世服务就不被允许,何为隐世,未指定包名,未指定类名
1
2
3
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
  • ServiceManager中获取ActivityManagerIBinder对象
  • 通过IPC获取了ActivityManagerService对象
  • 每个系统服务都采用了AIDL的方式进行,不直接对外暴露代理
IActivityManager.aidl

该文件对应的native实现

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
class BpActivityManager : public BpInterface<IActivityManager>
{
public:
explicit BpActivityManager(const sp<IBinder>& impl)
: BpInterface<IActivityManager>(impl)
{
}

virtual int openContentUri(const String16& stringUri)
{
Parcel data, reply;
data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor());
data.writeString16(stringUri);
status_t ret = remote()->transact(OPEN_CONTENT_URI_TRANSACTION, data, & reply);
int fd = -1;
if (ret == NO_ERROR) {
int32_t exceptionCode = reply.readExceptionCode();
if (!exceptionCode) {
// Success is indicated here by a nonzero int followed by the fd;
// failure by a zero int with no data following.
if (reply.readInt32() != 0) {
fd = fcntl(reply.readParcelFileDescriptor(), F_DUPFD_CLOEXEC, 0);
}
} else {
// An exception was thrown back; fall through to return failure
ALOGD("openContentUri(%s) caught exception %d\n",
String8(stringUri).string(), exceptionCode);
}
}
return fd;
}
};
ActivityManagerService.startService
1
2
3
4
5
6
7
8
9
10
11
12
public class ActivityManagerService extends IActivityManager.Stub {
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
...
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
...
}
}
  • ActivityManagerService就是ActivityManager定义的AIDL的具体实现
  • 调用ActiveServices.startServiceLocked
ActiveServices.startServiceLocked
1
2
3
4
5
6
7
8
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
throws TransactionTooLargeException {
...
//启动服务
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
...
}

检查Service调用者合法性。创建并缓存Service信息

ActiveServices.startServiceInnerLocked
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
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;
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 (DEBUG_DELAYED_SERVICE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
} else if (DEBUG_DELAYED_STARTS) {
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
}
if (first) {
smap.rescheduleDelayedStartsLocked();
}
} else if (callerFg || r.fgRequired) {
smap.ensureNotStartingBackgroundLocked(r);
}

return r.name;
}

调用bringUpServiceLocked,处理返回结果

ActiveService.bringUpServiceLocked
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
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
if (r.app != null && r.app.thread != null) {
//服务已经启动
sendServiceArgsLocked(r, execInFg, false);
return null;
}

...
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
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);
}

// If a dead object exception was thrown -- fall through to
// restart the application.
}
...
}

如果服务已经启动,调用sendserviceArgsLocked。首次创建。获取进程信息。调用realStartServiceLocked

ActiveServices.realStartServiceLocked
1
2
3
4
5
6
7
8
9
10
11
12
13
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
final boolean newService = app.services.add(r);
...
...
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
...

sendServiceArgsLocked(r, execInFg, true);
}

更新服务优先级。通知ApplicationThread创建启动Service。之后调用sendServiceArgsLocked,其作用,处理Service参数,并回调onStartCommand

ActivityThread.scheduleCreateService
1
2
3
4
5
6
7
8
9
10
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);
}
  • H Handler发出消息,创建service

  • 总结; 在8.0中,一个服务的启动流程是:
    ContextImpl.startService -> startCommonService->ActivityManager.getService->ServiceManager.getService->(IPC) AMS.startService-> ActiveService.startServiceLocked->startServiceInnerLocked->bringUpServiceLocked->realStartServiceLocked->ApplicationThread.scheduleCreateService->H.handleCreateService

BindService

bindService的流程,跟startService很相似。

ActiveServices.bindServiceLocked
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
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
...
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
...

if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
...
}

ServiceRecord存储每个Binder,也就是ServiceConnection。内部的数据结构都是Set,确保Binder唯一。调用bringUpServiceLocked

ActiveServices.bringUpServiceLocked
1
2
3
4
5
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {

}

首次绑定Service的过程和startService一样。也是调用realStartServiceLocked。非首次也是调用sendServiceArgsLocked,这个函数中,如果有startService的话,那么会发出消息通知ApplicationThread需要处理onStartCommandBindService下,会直接返回

1
2
3
4
5
6
7
8
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
//创建过程一样

...
requestServiceBindingsLocked(r, execInFg);
}

创建过程一样。创建完之后会检查是否有Binder。如果有直接通知ApplicationThread需要绑定服务。

总结

客户端发起启动服务请求,通过IPC的方式通知SystemServer进程中的ActivityManagerService,然后通知ApplicationThread创建服务

时序图

StartService

startService

BindService

bindService