android startService流程梳理筆記
1、ContextWrapper.startService
startService是Context的方法,Activity、Service都繼承自ContextWrapper,而ContextWrapper又繼承自Context,BroadcastReceiver的onReceive方法中有個參數(shù)是Context類型的,所以我們在Activity、Service、BroadcastReceiver中都可以調(diào)用startService方法,當在Activity等中調(diào)用startService時,首先會調(diào)用到ContextWrapper的startService方法:
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
2、ContextImpl.startService
mBase是ContextImpl的實例,從名字也可以看到ContextImpl也是Context的子類,從ContextWrapper的名字也可以看到,它只是Context的包裝類,其函數(shù)內(nèi)部的實現(xiàn)都是通過調(diào)用內(nèi)部ContextImpl類的實例mBase來完成實際請求,這被稱為裝飾者模式。
ContextImpl的startService直接調(diào)用startServiceAsUser,在startServiceAsUser中調(diào)用ActivityManagerNative.getDefault().startService,ActivityManagerNative.getDefault()返回一個IActivityManager對象,典型的Binder通信。所以接下來會通過ActivityManagerProxy的startService經(jīng)由Binder調(diào)用到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),然后調(diào)用ActiveServices的startServiceLocked方法(在舊版本中這個方法在ActivityManagerService中),在startServiceLocked中,首先通過retrieveServiceLocked檢索我們調(diào)用startService時傳入的Intent信息,將結(jié)果存入ServiceLookupResult.record中(ServiceRecord),緊接著調(diào)用ActiveServices的bringUpServiceLocked方法。
在bringUpServiceLocked中調(diào)用ActivityManagerService的startProcessLocked獲得一個ProcessRecord對象并將其加入到mPendingServices隊列中。startServiceLocked、bringUpServiceLocked都是從ActivityManagerService中調(diào)用過來的,所以是一直運行在ActivityaManagerService進程中,再調(diào)用ActivityManagerService的方法就是直接調(diào)用,而不用通過IPC。
ActivityManagerService中有兩個重載形式的startProcessLocked,首先進入?yún)?shù)多的那一個,通過newProcessRecordLocked獲得一個ProcessRecord對象,然后把這個對象作為參數(shù)調(diào)用另一個形式的startProcessLocked,在這個startProcessLocked中,調(diào)用Process.start創(chuàng)建一個新的進程,將返回的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中創(chuàng)建了一個進程,然后調(diào)用了ActivityThread的main函數(shù)。
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對象,并調(diào)用其attach方法,參數(shù)表示是否是系統(tǒng)進程。這里已經(jīng)是在新進程里了。在attach中,又調(diào)用了ActivityManagerNative.getDefault().attachApplication(mAppThread)。同樣,經(jīng)由Binder由ActivityManagerProxy到了ActivityManagerService的attachApplication方法,在attachApplication中直接調(diào)用attachApplicationLocked。
在attachApplicationLocked中,通過新進程的PID獲得在第3步中放入mPidSelfLocked列表中的ProcessRecord對象,然后調(diào)用ActiveyServices的attachApplicationLocked方法,在這個方法中通過進程PID與進程名找到在第3步中放入mPendingServices中的ServiceRecord對象,再以這個找到的ServiceRecord對象與傳入的ProcessRecord對象為參數(shù)調(diào)用realStartServiceLocked,這個函數(shù)也在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,調(diào)用其scheduleCreateService方法,同ActivityManagerProxy一樣,調(diào)用的是ApplicationThreadProxy的scheduleCreateService,然后經(jīng)由Binder到ApplicationThread的scheduleCreateService(ApplicationThread是ActivityThread的私有內(nèi)部類)。
7、ApplicationThread.scheduleCreateService與ActivityThread.handleCreateService
在ApplicationThread的scheduleCreateService中調(diào)用了外部類ActivityThread的queueOrSendMessage方法,向H中sendMessage(H繼承自Handler),接下來肯定到了H的handleMessage,在handleMessage中走CREATE_SERVICE的switch case,調(diào)用外部類ActivityThread的handleCreateService方法。
在handleCreateService通過JAVA的ClassLoader load加載要啟動的Service的類,并通過newInstance新建一個Service的實例,new ContextImpl,makeApplication并跟新建的Service實例attach,然后調(diào)用我們熟悉的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());
// 調(diào)用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) {
...
}
}
總結(jié):
1、調(diào)用ContextImpl的startService,通過Binder進入ActivityManagerService的進程執(zhí)行ActivityManagerService的startService方法。
2、在startService過程中新建一個進程,在新建的進程中創(chuàng)建Looper,調(diào)用ActivityThread的attach方法,然后就又進入了ActivityManagerService的進程。
3、獲取要在新進程啟動的服務(wù)的相關(guān)信息,在ActivityManagerService中通過ApplicationThreadProxy又進入Service進程,Service的進程啟起來,調(diào)用我們熟悉的Service的onCreate方法。

浙公網(wǎng)安備 33010602011771號