1.service的启动流程
这里先讲解采用startService的方式启动
1.1 Service -> AMS
service的启动入口类是ConetxtImpl
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
//获取AM的binder对象,与AMS进行IPC
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
1.2 AMS -> Service
AMS中的startService
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
启动工作在ActiveServices
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//ServiceRecord 已经存在 也就是说该Service已经启动过了
if (r.app != null && r.app.thread != null) {
// 调用onStartCommand 也就是说再次启动service只会走onStartCommand
sendServiceArgsLocked(r, execInFg, false);
return null;
}
final String procName = r.processName;
ProcessRecord app;
//获取ProcessRecord 判断当前进程是否存在
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {
try {
//启动service
realStartServiceLocked(r, app, execInFg);
return null;
}
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {
//进程不存在,创建进程
mAm.startProcessLocked();
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
return null;
}
注意:==如果该service已经被启动了,如果再次启动只会走onStartCommand就return,也就是说onStartCommand可能被多次调用,但是onCreate只会被调用一次。==
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
r.app = app;
final boolean newService = app.services.add(r);
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
mAm.updateOomAdjLocked();
boolean created = false;
try {
//ipc 调用ApplicationThread
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} finally {
if (!created) {
// Cleanup.
if (newService) {
app.services.remove(r);
r.app = null;
}
// Retry.
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
//
sendServiceArgsLocked(r, execInFg, true);
}
从上面的流程我们可以看出,Service和Activity的启动流程是大同小异的。
1.3 ActivityThread
private void handleCreateService(CreateServiceData data) {
//1
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
//2
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
}
try {
//3
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
//4
Application app = packageInfo.makeApplication(false, mInstrumentation);
//5
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
mServices.put(data.token, service);
//5
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
小结:
- 1.获取安装包的信息
-
- 通过类加载器加载Service实例
- 3.创建ContextImpl
- 4.获取Application
- 5.attach一些信息到Service
- 6.向AMS汇报,service已经启动 的