1、ContextWrapper.startService
startService是Context的方法,Activity、Service都继承自ContextWrapper,而ContextWrapper又继承自Context,BroadcastReceiver的onReceive方法中有个参数是Context类型的,所以我们在Activity、Service、BroadcastReceiver中都可以调用startService方法,当在Activity等中调用startService时,首先会调用到ContextWrapper的startService方法:
public
ComponentName startService(Intent service) {
return
mBase.startService(service);
}
|
2、ContextImpl.startService
mBase是ContextImpl的实例,从名字也可以看到ContextImpl也是Context的子类,从ContextWrapper的名字也可以看到,它只是Context的包装类,其函数内部的实现都是通过调用内部ContextImpl类的实例mBase来完成实际请求,这被称为装饰者模式。
ContextImpl的startService直接调用startServiceAsUser,在startServiceAsUser中调用ActivityManagerNative.getDefault().startService,ActivityManagerNative.getDefault()返回一个IActivityManager对象,典型的Binder通信。所以接下来会通过ActivityManagerProxy的startService经由Binder调用到ActivityManagerService(继承自ActivityManagerNative)的startService方法。
public
ComponentName startServiceAsUser(Intent service, UserHandle user) {
try
{
service.setAllowFds(
false
);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
...
return
cn;
}
catch
(RemoteException e) {
return
null
;
}
}
|
3、ActivityManagerService.startService与ActiveServices
在ActivityManagerService的startService中,首先检查Caller的合法性(PID、UID),然后调用ActiveServices的startServiceLocked方法(在旧版本中这个方法在ActivityManagerService中),在startServiceLocked中,首先通过retrieveServiceLocked检索我们调用startService时传入的Intent信息,将结果存入ServiceLookupResult.record中(ServiceRecord),紧接着调用ActiveServices的bringUpServiceLocked方法。
在bringUpServiceLocked中调用ActivityManagerService的startProcessLocked获得一个ProcessRecord对象并将其加入到mPendingServices队列中。startServiceLocked、bringUpServiceLocked都是从ActivityManagerService中调用过来的,所以是一直运行在ActivityaManagerService进程中,再调用ActivityManagerService的方法就是直接调用,而不用通过IPC。
ActivityManagerService中有两个重载形式的startProcessLocked,首先进入参数多的那一个,通过newProcessRecordLocked获得一个ProcessRecord对象,然后把这个对象作为参数调用另一个形式的startProcessLocked,在这个startProcessLocked中,调用Process.start创建一个新的进程,将返回的Process.ProcessStartResult对象、新进程的PID及获得的ProcessRecord对象放入mPidSelfLocked列表中。
final
ProcessRecord startProcessLocked(String processName,
ApplicationInfo info,
boolean
knownToBeDead,
int
intentFlags,
String hostingType, ComponentName hostingName,
boolean
allowWhileBooting,
boolean
isolated) {
...
app = newProcessRecordLocked(
null
, info, processName, isolated);
...
startProcessLocked(app, hostingType, hostingNameStr);
return
(app.pid !=
0
) ? app :
null
;
}
private
final
void
startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
...
Process.ProcessStartResult startResult = Process.start(
"android.app.ActivityThread"
,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion,
null
,
null
);
...
synchronized
(mPidsSelfLocked) {
this
.mPidsSelfLocked.put(startResult.pid, app);
...
}
...
}
|
4、ActivityThread.main
在Process.start中创建了一个进程,然后调用了ActivityThread的main函数。
public
static
void
main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread =
new
ActivityThread();
thread.attach(
false
);
if
(sMainThreadHandler ==
null
) {
sMainThreadHandler = thread.getHandler();
}
...
Looper.loop();
...
}
|
5、ActivityManagerService.attachApplication
在main中新建一个ActivityThread对象,并调用其attach方法,参数表示是否是系统进程。这里已经是在新进程里了。在attach中,又调用了ActivityManagerNative.getDefault().attachApplication(mAppThread)。同样,经由Binder由ActivityManagerProxy到了ActivityManagerService的attachApplication方法,在attachApplication中直接调用attachApplicationLocked。
在attachApplicationLocked中,通过新进程的PID获得在第3步中放入mPidSelfLocked列表中的ProcessRecord对象,然后调用ActiveyServices的attachApplicationLocked方法,在这个方法中通过进程PID与进程名找到在第3步中放入mPendingServices中的ServiceRecord对象,再以这个找到的ServiceRecord对象与传入的ProcessRecord对象为参数调用realStartServiceLocked,这个函数也在ActiveServices中。
private
final
boolean
attachApplicationLocked(IApplicationThread thread, nt pid) {
ProcessRecord app;
if
(pid != MY_PID && pid >=
0
) {
synchronized
(mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
}
else
{
app =
null
;
}
...
mServices.attachApplicationLocked(app, processName);
...
}
boolean
attachApplicationLocked(ProcessRecord proc, String processName)
throws
Exception {
boolean
didSomething =
false
;
// Collect any services that are waiting for this process to come up.
if
(mPendingServices.size() >
0
) {
ServiceRecord sr =
null
;
try
{
for
(
int
i=
0
; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
if
(proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue
;
}
mPendingServices.remove(i);
i--;
realStartServiceLocked(sr, proc);
didSomething =
true
;
}
}
catch
(Exception e) {
Slog.w(TAG,
"Exception in new application when starting service "
+ sr.shortName, e);
throw
e;
}
}
...
}
|
6、ActiveServices.realStartServiceLocked
在realStartServiceLocked中,取得传入的ProcessRecord对象的IApplicationThread类型的成员变量thread,调用其scheduleCreateService方法,同ActivityManagerProxy一样,调用的是ApplicationThreadProxy的scheduleCreateService,然后经由Binder到ApplicationThread的scheduleCreateService(ApplicationThread是ActivityThread的私有内部类)。
7、ApplicationThread.scheduleCreateService与ActivityThread.handleCreateService
在ApplicationThread的scheduleCreateService中调用了外部类ActivityThread的queueOrSendMessage方法,向H中sendMessage(H继承自Handler),接下来肯定到了H的handleMessage,在handleMessage中走CREATE_SERVICE的switch case,调用外部类ActivityThread的handleCreateService方法。
在handleCreateService通过JAVA的ClassLoader load加载要启动的Service的类,并通过newInstance新建一个Service的实例,new ContextImpl,makeApplication并跟新建的Service实例attach,然后调用我们熟悉的Service的onCreate方法,至此Service启动成功。
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 packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service =
null
;
try
{
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
}
catch
(Exception e) {
...
}
try
{
if
(localLOGV) Slog.v(TAG,
"Creating service "
+ data.info.name);
ContextImpl context =
new
ContextImpl();
context.init(packageInfo,
null
,
this
);
Application app = packageInfo.makeApplication(
false
, mInstrumentation);
context.setOuterContext(service);
service.attach(context,
this
, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
// 调用Service的onCreate,即要启动的Service的onCreate
service.onCreate();
mServices.put(data.token, service);
try
{
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token,
0
,
0
,
0
);
}
catch
(RemoteException e) {
// nothing to do.
}
}
catch
(Exception e) {
...
}
}
|
总结:
1、调用ContextImpl的startService,通过Binder进入ActivityManagerService的进程执行ActivityManagerService的startService方法。
2、在startService过程中新建一个进程,在新建的进程中创建Looper,调用ActivityThread的attach方法,然后就又进入了ActivityManagerService的进程。
3、获取要在新进程启动的服务的相关信息,在ActivityManagerService中通过ApplicationThreadProxy又进入Service进程,Service的进程启起来,调用我们熟悉的Service的onCreate方法。