原文
http://www.2cto.com/kf/201202/118540.html
為什麼寫這篇文章呢?前段時間在研究telephony時,一直沒有在framework下發現對telephony的初始化(PhoneFactory.java中的makeDefaultPhones函數)的調用。結果全域搜尋之後發現在application PhoneApp(packages/apps/Phone)中調用了。但是application PhoneApp既沒有被Broadcast喚醒,也沒有被其他service調用,那麼是android是通過什麼方式來啟動PhoneApp,所以就發現了屬性android:persistent。
在AndroidManifest.xml定義中,application有這麼一個屬性android:persistent,根據字面意思來理解就是說該應用是可持久的,也即是常駐的應用。其實就是這麼個理解,被android:persistent修飾的應用會在系統啟動之後被AM啟動。
AM首先去PM(PackageManagerService)中去尋找設定了android:persistent的應用。
[c-sharp] www.2cto.com
public void systemReady(final Runnable goingCallback) {
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try {
List apps = AppGlobals.getPackageManager().
getPersistentApplications(STOCK_PM_FLAGS);
if (apps != null) {
int N = apps.size();
int i;
for (i=0; i<N; i++) {
ApplicationInfo info
= (ApplicationInfo)apps.get(i);
if (info != null &&
!info.packageName.equals("android")) {
addAppLocked(info);
}
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}
}
假如該被android:persistent修飾的應用此時並未啟動並執行話,那麼AM將調用startProcessLocked啟動該app,關於startProcessLocked不再描述,另外一篇文章《How to start a new process for Android?》中做了詳細的介紹。
app的啟動過程就是啟動app所在的package對應的進程。
[c-sharp] www.2cto.com
final ProcessRecord addAppLocked(ApplicationInfo info) {
ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
if (app == null) {
app = newProcessRecordLocked(null, info, null);
mProcessNames.put(info.processName, info.uid, app);
updateLruProcessLocked(app, true, true);
}
if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
== (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
app.persistent = true;
app.maxAdj = CORE_SERVER_ADJ;
}
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
startProcessLocked(app, "added application", app.processName);
}
return app;
}
下面介紹app所在的package對應的進程啟動完成之後,app是如何被create的。
從文章《How to start a new process for Android?》中可知,zygote在建立新的進程均會啟動它的mainThread android.app.ActivityThread,因此我們從ActivityThread的main函數中接著分析app的create過程。
在main中有下面這個操作
[c-sharp] www.2cto.com
thread.attach(false);
在attach過程中,ActivityThread會將對應的application attach到AM中去,交與AM去管理。這裡需要注意一個變數
[c-sharp] www.2cto.com
final ApplicationThread mAppThread = new ApplicationThread();
mAppThread是一個ApplicationThread對象,mAppThread可以看作是當前進程主線程的核心,它負責處理本進程與其他進程(主要是AM)之間的通訊,同時通過attachApplication將mAppThread的代理Binder傳遞給AM。
[c-sharp] www.2cto.com
private final void attach(boolean system) {
sThreadLocal.set(this);
mSystemThread = system;
if (!system) {
ViewRoot.addFirstDrawHandler(new Runnable() {
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
}
}
上面的attach代碼中,我們順著IPC調用AM的attachApplication過程再往下看。
在該過程中,AM調用到了IPC通訊調用mAppThread的bindApplication;
[c-sharp]
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
thread.bindApplication(processName, app.instrumentationInfo != null
? app.instrumentationInfo : app.info, providers,
app.instrumentationClass, app.instrumentationProfileFile,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
isRestrictedBackupMode || !normalMode,
mConfiguration, getCommonServicesLocked());
updateLruProcessLocked(app, false, true);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
}
mAppThread的bindApplication再通過訊息機制向ActivityThread自身維護的handler發送BIND_APPLICATION訊息。下面看看ActivityThread自身維護的handler對訊息BIND_APPLICATION的處理,最終會調用到handleBindApplication函數
你會發現在handleBindApplication函數中有這麼一句
[c-sharp] www.2cto.com
mInstrumentation.callApplicationOnCreate(app);
我們最終在繞了好大一圈之後,調用了app的onCreate函數來啟動這個application