理解Android進程啟動之全過程
一. 概述
Android系統將進程做得很友好的封裝,對于上層app開發者來說進程幾乎是透明的. 了解Android的朋友,一定知道Android四大組件,但對于進程可能會相對較陌生. 一個進程里面可以跑多個app(通過share uid的方式), 一個app也可以跑在多個進程里(通過配置Android:process屬性).
再進一步進程是如何創建的, 可能很多人不知道fork的存在. 在我的文章 理解Android進程創建流程 集中一點詳細介紹了 Process.start 的過程是如何一步步創建進程.本文則是從另個角度來全局性講解android進程啟動全過程所涉及的根脈, 先來看看AMS.startProcessLocked方法.
二. 四大組件與進程
2.1 startProcessLocked
在 ActivityManagerService.java 關于啟動進程有4個同名不同參數的重載方法, 為了便于說明,以下4個方法依次記為 1(a) , 1(b) , 2(a) , 2(b) :
//方法 1(a)
final ProcessRecord startProcessLocked(
String processName, ApplicationInfo info, boolean knownToBeDead,
int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, boolean keepIfLarge)
//方法 1(b)
final ProcessRecord startProcessLocked(
String processName, ApplicationInfo info, boolean knownToBeDead,
int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid,
boolean keepIfLarge, String abiOverride, String entryPoint,
String[] entryPointArgs, Runnable crashHandler)
//方法 2(a)
private final void startProcessLocked(
ProcessRecord app, String hostingType, String hostingNameStr)
//方法 2(b)
private final void startProcessLocked(
ProcessRecord app, String hostingType, String hostingNameStr,
String abiOverride, String entryPoint, String[] entryPointArgs)</code></pre>
1(a) ==> 1(b):方法1(a)將isolatedUid=0,其他參數賦值為null,再調用給1(b)
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
2(a) ==> 2(b):方法2(a)將其他3個參數abiOverride,entryPoint, entryPointArgs賦值為null,再調用給2(b)
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */,
null /* entryPoint */, null /* entryPointArgs */);
}
小結:
- 1(a),1(b)的第一個參數為String類型的進程名processName,
- 2(a), 2(b)的第一個參數為ProcessRecord類型進程記錄信息ProcessRecord;
- 1系列的方法最終調用到2系列的方法;
2.2 四大組件與進程
Activity, Service, ContentProvider, BroadcastReceiver這四大組件,在啟動的過程,當其所承載的進程不存在時需要先創建進程. 這個創建進程的過程是調用前面講到的startProcessLocked方法1(a) . 調用流程: 1(a) => 1(b) ==> 2(b). 下面再簡單說說這4大組件與進程創建是在何時需要創建的.
2.2.1 Activity
啟動Activity過程: 調用startActivity,該方法經過層層調用,最終會調用ActivityStackSupervisor.java中的 startSpecificActivityLocked ,當activity所屬進程還沒啟動的情況下,則需要創建相應的進程.
[-> ActivityStackSupervisor.java]
void startSpecificActivityLocked(...) {
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
if (app != null && app.thread != null) {
... //進程已創建的case
return
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
2.2.2 Service
啟動服務過程: 調用startService,該方法經過層層調用,最終會調用ActiveServices.java中的 bringUpServiceLocked ,當Service進程沒有啟動的情況(app==null), 則需要創建相應的進程. 更多關于Service, 見startService流程分析
[-> ActiveServices.java]
private final String bringUpServiceLocked(...){
...
ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app == null) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
...
}
}
...
}
2.2.3 ContentProvider
ContentProvider處理過程: 調用ContentResolver.query該方法經過層層調用, 最終會調用到AMS.java中的 getContentProviderImpl ,當ContentProvider所對應進程不存在,則需要創建新進程. 更多關于ContentProvider,見 理解ContentProvider原理(一)
[-> AMS.java]
private final ContentProviderHolder getContentProviderImpl(...) {
...
ProcessRecord proc = getProcessRecordLocked(cpi.processName, cpr.appInfo.uid, false);
if (proc != null && proc.thread != null) {
... //進程已創建的case
} else {
proc = startProcessLocked(cpi.processName,
cpr.appInfo, false, 0, "content provider",
new ComponentName(cpi.applicationInfo.packageName,cpi.name),
false, false, false);
}
...
}
2.2.4 Broadcast
廣播處理過程: 調用sendBroadcast,該方法經過層層調用, 最終會調用到BroadcastQueue.java中的 processNextBroadcast ,當BroadcastReceiver所對應的進程尚未啟動,則創建相應進程. 更多關于broadcast, 見 Android Broadcast廣播機制分析 .
[-> BroadcastQueue.java]
final void processNextBroadcast(boolean fromMsg) {
...
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
if (app != null && app.thread != null) {
... //進程已創建的case
return
}
if ((r.curApp=mService.startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
"broadcast", r.curComponent,
(r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
== null) {
...
}
...
}</code></pre>
2.3 小節
Activity, Service, ContentProvider, BroadcastReceiver這四大組件在啟動時,當所承載的進程不存在時,都需要創建. 進程的創建過程交由系統進程system_server來完成的.

簡稱:
- ATP: ApplicationThreadProxy
- AT: ApplicationThread (繼承于ApplicationThreadNative)
- AMP: ActivityManagerProxy
- AMS: ActivityManagerService (繼承于ActivityManagerNative)
- system_server進程中調用 startProcessLocked 方法,該方法最終通過socket方式,將需要創建新進程的消息告知Zygote進程,并阻塞等待Socket返回新創建進程的pid;
- Zygote進程接收到system_server發送過來的消息, 則通過fork的方法,將zygote自身進程復制生成新的進程,并將ActivityThread相關的資源加載到新進程app process,這個進程可能是用于承載activity等組件;
- 創建完新進程后fork返回兩次, 在新進程app process向servicemanager查詢system_server進程中binder服務端AMS,獲取相對應的Client端,也就是AMP. 有了這一對binder c/s對, 那么app process便可以通過binder向跨進程system_server發送請求,即attachApplication()
- system_server進程接收到相應binder操作后,經過多次調用,利用ATP向app process發送binder請求, 即bindApplication.
system_server擁有ATP/AMS, 每一個新創建的進程都會有一個相應的AT/AMS,從而可以跨進程 進行相互通信. 這便是進程創建過程的完整生態鏈.
三. 進程啟動全過程
前面剛已介紹四大組件的創建進程的過程是調用1(a) startProcessLocked 方法,該方法會再調用1(b)方法. 接下來從該方法開始往下講述.
3.1 AMS.startProcessLocked
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;
if (!isolated) {
//根據進程名和uid檢查相應的ProcessRecord
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
//如果當前處于后臺進程,檢查當前進程是否處于bad進程列表
if (mBadProcesses.get(info.processName, info.uid) != null) {
return null;
}
} else {
//當用戶明確地啟動進程,則清空crash次數,以保證其不處于bad進程直到下次再彈出crash對話框。
mProcessCrashTimes.remove(info.processName, info.uid);
if (mBadProcesses.get(info.processName, info.uid) != null) {
mBadProcesses.remove(info.processName, info.uid);
if (app != null) {
app.bad = false;
}
}
}
} else {
//對于孤立進程,無法再利用已存在的進程
app = null;
}
//當存在ProcessRecord,且已分配pid(正在啟動或者已經啟動),
// 且caller并不認為該進程已死亡或者沒有thread對象attached到該進程.則不應該清理該進程
if (app != null && app.pid > 0) {
if (!knownToBeDead || app.thread == null) {
//如果這是進程中新package,則添加到列表
app.addPackage(info.packageName, info.versionCode, mProcessStats);
return app;
}
//當ProcessRecord已經被attached到先前的一個進程,則殺死并清理該進程
killProcessGroup(app.info.uid, app.pid);
handleAppDiedLocked(app, true, true);
}
String hostingNameStr = hostingName != null? hostingName.flattenToShortString() : null;
if (app == null) {
// 創建新的Process Record對象
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
return null;
}
app.crashHandler = crashHandler;
} else {
//如果這是進程中新package,則添加到列表
app.addPackage(info.packageName, info.versionCode, mProcessStats);
}
//當系統未準備完畢,則將當前進程加入到mProcessesOnHold
if (!mProcessesReady && !isAllowedWhileBooting(info) && !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
return app;
}
// 啟動進程【見小節3.2】
startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
return (app.pid != 0) ? app : null;
}</code></pre>
主要功能:
- 對于非isolated進程,則根據進程名和uid來查詢相應的ProcessRecord結構體. 如果當前進程處于后臺且當前進程處于mBadProcesses列表,則直接返回;否則清空crash次數,以保證其不處于bad進程直到下次再彈出crash對話框。
- 當存在ProcessRecord,且已分配pid(正在啟動或者已經啟動)的情況下
- 當caller并不認為該進程已死亡或者沒有thread對象attached到該進程.則不應該清理該進程,則直接返回;
- 否則殺死并清理該進程;
</li>
- 當ProcessRecord為空則新建一個,當創建失敗則直接返回;
- 當系統未準備完畢,則將當前進程加入到mProcessesOnHold, 并直接返回;
- 最后啟動新進程,其中參數含義:
- hostingType可取值為”activity”,”service”,”broadcast”,”content provider”;
- hostingNameStr數據類型為ComponentName,代表的是具體相對應的組件名.
</ul> </li>
</ul>
3.2 AMS.startProcessLocked
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
long startTime = SystemClock.elapsedRealtime();
//當app的pid大于0且不是當前進程的pid,則從mPidsSelfLocked中移除該app.pid
if (app.pid > 0 && app.pid != MY_PID) {
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
app.setPid(0);
}
//從mProcessesOnHold移除該app
mProcessesOnHold.remove(app);
updateCpuStats(); //更新cpu統計信息
try {
try {
if (AppGlobals.getPackageManager().isPackageFrozen(app.info.packageName)) {
//當前package已被凍結,則拋出異常
throw new RuntimeException("Package " + app.info.packageName + " is frozen!");
}
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
//通過Package Manager獲取gids
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName, app.userId);
MountServiceInternal mountServiceInternal = LocalServices.getService(
MountServiceInternal.class);
mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
app.info.packageName);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
//添加共享app和gids,用于app直接共享資源
if (ArrayUtils.isEmpty(permGids)) {
gids = new int[2];
} else {
gids = new int[permGids.length + 2];
System.arraycopy(permGids, 0, gids, 2, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
//根據不同參數,設置相應的debugFlags
...
app.gids = gids;
app.requiredAbi = requiredAbi;
app.instructionSet = instructionSet;
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
//請求Zygote創建新進程[見3.3]
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
...
if (app.persistent) {
Watchdog.getInstance().processStarted(app.processName, startResult.pid);
}
//重置ProcessRecord的成員變量
app.setPid(startResult.pid);
app.usingWrapper = startResult.usingWrapper;
app.removed = false;
app.killed = false;
app.killedByAm = false;
//將新創建的進程加入到mPidsSelfLocked
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
//延遲發送消息PROC_START_TIMEOUT_MSG
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
} catch (RuntimeException e) {
app.setPid(0); //進程創建失敗,則重置pid
}
}</code></pre>
- 根據不同參數,設置相應的debugFlags,比如在AndroidManifest.xml中設置androidd:debuggable為true,代表app運行在debug模式,則增加debugger標識以及開啟JNI check功能
- 調用Process.start來創建新進程;
- 重置ProcessRecord的成員變量, 一般情況下超時10s后發送PROC_START_TIMEOUT_MSG的handler消息;
關于Process.start()是通過socket通信告知Zygote創建fork子進程,創建新進程后將ActivityThread類加載到新進程,并調用ActivityThread.main()方法。詳細過程見 理解Android進程創建流程 ,接下來進入AT.main方法.
3.3 ActivityThread.main
[-> ActivityThread.java]
public static void main(String[] args) {
//性能統計默認是關閉的
SamplingProfilerIntegration.start();
//將當前進程所在userId賦值給sCurrentUser
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
AndroidKeyStoreProvider.install();
//確保可信任的CA證書存放在正確的位置
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
//創建主線程的Looper對象, 該Looper是不運行退出
Looper.prepareMainLooper();
//創建ActivityThread對象
ActivityThread thread = new ActivityThread();
//建立Binder通道 【見流程3.4】
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
// 當設置為true時,可打開消息隊列的debug log信息
if (false) {
Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop(); //消息循環運行
throw new RuntimeException("Main thread loop unexpectedly exited");
}</code></pre>
-
創建主線程的Looper對象: 該Looper是不運行退出. 也就是說主線程的Looper是在進程創建完成時自動創建完成,如果子線程也需要創建handler通信過程,那么就需要手動創建Looper對象,并且每個線程只能創建一次.
-
創建ActivityThread對象 thread = new ActivityThread() : 該過程會初始化幾個很重要的變量:
-
mAppThread = new ApplicationThread()
-
mLooper = Looper.myLooper()
-
mH = new H(), H 繼承于 Handler ;用于處理組件的生命周期.
</li>
-
attach過程是當前主線程向system_server進程通信的過程, 將thread信息告知AMS.接下來還會進一步說明該過程.
-
sMainThreadHandler通過getHandler(),獲取的對象便是 mH ,這就是主線程的handler對象.
</ul>
之后主線程調用Looper.loop(),進入消息循環狀態, 當沒有消息時主線程進入休眠狀態, 一旦有消息到來則喚醒主線程并執行相關操作.
3.4. ActivityThread.attach
[-> ActivityThread.java]
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
//開啟虛擬機的jit即時編譯功能
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
//創建ActivityManagerProxy對象
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
//調用基于IActivityManager接口的Binder通道【見流程3.5】
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
//觀察是否快接近heap的上限
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
if (dalvikUsed > ((3*dalvikMax)/4)) {
mSomeActivitiesChanged = false;
try {
//當已用內存超過最大內存的3/4,則請求釋放內存空間
mgr.releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
}
}
}
});
} else {
...
}
//添加dropbox日志到libcore
DropBox.setReporter(new DropBoxReporter());
//添加Config回調接口
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
synchronized (mResourcesManager) {
if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(newConfig)) {
mPendingConfiguration = newConfig;
sendMessage(H.CONFIGURATION_CHANGED, newConfig);
}
}
}
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
}
});
}</code></pre>
對于非系統attach的處理流程:
-
創建線程來開啟虛擬機的jit即時編譯;
-
通過binder, 調用到AMS.attachApplication, 其參數mAppThread的數據類型為 ApplicationThread
-
觀察是否快接近heap的上限,當已用內存超過最大內存的3/4,則請求釋放內存空間
-
添加dropbox日志到libcore
-
添加Config回調接口
3.5 AMP.attachApplication
[-> ActivityManagerProxy.java]
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app.asBinder());
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0); //【見流程3.6】
reply.readException();
data.recycle();
reply.recycle();
}
此處 descriptor = “android.app.IActivityManager”
3.6 AMN.onTransact
[-> ActivityManagerNative.java]
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
//獲取ApplicationThread的binder代理類 ApplicationThreadProxy
IApplicationThread app = ApplicationThreadNative.asInterface(
data.readStrongBinder());
if (app != null) {
attachApplication(app); //此處是ActivityManagerService類中的方法 【見流程3.7】
}
reply.writeNoException();
return true;
}
}
}
3.7 AMS.attachApplication
[-> ActivityManagerService.java]
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid); // 【見流程3.8】
Binder.restoreCallingIdentity(origId);
}
}
此處的 thread 便是ApplicationThreadProxy對象,用于跟前面通過Process.start()所創建的進程中ApplicationThread對象進行通信.
3.8 AMS.attachApplicationLocked
[-> ActivityManagerService.java]
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid); // 根據pid獲取ProcessRecord
}
} else {
app = null;
}
if (app == null) {
if (pid > 0 && pid != MY_PID) {
//ProcessRecord為空,則殺掉該進程
Process.killProcessQuiet(pid);
} else {
//退出新建進程的Looper
thread.scheduleExit();
}
return false;
}
//還剛進入attach過程,此時thread應該為null,若不為null則表示該app附到上一個進程,則立刻清空
if (app.thread != null) {
handleAppDiedLocked(app, true, true);
}
final String processName = app.processName;
try {
//綁定死亡通知
AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
startProcessLocked(app, "link fail", processName); //重新啟動進程
return false;
}
//重置進程信息
app.makeActive(thread, mProcessStats); //執行完該語句,則app.thread便不再為空
app.curAdj = app.setAdj = -100;
app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); //移除進程啟動超時的消息
//系統處于ready狀態或者該app為FLAG_PERSISTENT進程,則為true
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
//app進程存在正在啟動中的provider,則超時10s后發送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息
if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
}
try {
...
ensurePackageDexOpt(app.instrumentationInfo != null
? app.instrumentationInfo.packageName
: app.info.packageName);
ApplicationInfo appInfo = app.instrumentationInfo != null
? app.instrumentationInfo : app.info;
...
// 綁定應用 [見流程3.9]
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
//更新進程LRU隊列
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
//每當bind操作失敗,則重啟啟動進程, 此處有可能會導致進程無限重啟
startProcessLocked(app, "bind fail", processName);
return false;
}
mPersistentStartingProcesses.remove(app);
mProcessesOnHold.remove(app);
boolean badApp = false;
boolean didSomething = false;
//Activity: 檢查最頂層可見的Activity是否等待在該進程中運行
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
badApp = true;
}
}
//Service: 尋找所有需要在該進程中運行的服務
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
badApp = true;
}
}
//廣播:檢查是否在這個進程中有下一個廣播接收者
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {
badApp = true;
}
}
//檢查是否在這個進程中有下一個backup代理
if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {
ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
try {
thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
mBackupTarget.backupMode);
} catch (Exception e) {
badApp = true;
}
}
if (badApp) { //殺掉bad應用
app.kill("error during init", true);
handleAppDiedLocked(app, false, true);
return false;
}
if (!didSomething) {
updateOomAdjLocked(); //更新adj的值
}
return true;
}</code></pre>
-
根據pid從mPidsSelfLocked中查詢到相應的ProcessRecord對象app;
-
當app==null,意味著本次創建的進程不存在, 則直接返回.
-
還剛進入attach過程,此時thread應該為null,若不為null則表示該app附到上一個進程,則調用handleAppDiedLocked清理.
-
綁定死亡通知,當進程pid死亡時會通過binder死亡回調,來通知system_server進程死亡的消息;
-
重置ProcessRecord進程信息, 此時app.thread也賦予了新值,便不再為空.
-
app進程存在正在啟動中的provider,則超時10s后發送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息
-
調用thread.bindApplication綁定應用進程, 后面再進一步說明
-
處理Provider, Activity, Service, Broadcast相應流程
下面,再來說說thread.bindApplication的過程.
3.9 ATP.bindApplication
[-> ApplicationThreadNative.java ::ApplicationThreadProxy]
class ApplicationThreadProxy implements IApplicationThread {
...
public final void bindApplication(String packageName, ApplicationInfo info,
List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo,
Bundle testArgs, IInstrumentationWatcher testWatcher,
IUiAutomationConnection uiAutomationConnection, int debugMode,
boolean openGlTrace, boolean restrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeString(packageName);
info.writeToParcel(data, 0);
data.writeTypedList(providers);
if (testName == null) {
data.writeInt(0);
} else {
data.writeInt(1);
testName.writeToParcel(data, 0);
}
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
data.writeBundle(testArgs);
data.writeStrongInterface(testWatcher);
data.writeStrongInterface(uiAutomationConnection);
data.writeInt(debugMode);
data.writeInt(openGlTrace ? 1 : 0);
data.writeInt(restrictedBackupMode ? 1 : 0);
data.writeInt(persistent ? 1 : 0);
config.writeToParcel(data, 0);
compatInfo.writeToParcel(data, 0);
data.writeMap(services);
data.writeBundle(coreSettings);
mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
...
}
ATP經過binder ipc傳遞到ATN的onTransact過程.
3.10 ATN.onTransact
[-> ApplicationThreadNative.java]
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...
case BIND_APPLICATION_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
String packageName = data.readString();
ApplicationInfo info =
ApplicationInfo.CREATOR.createFromParcel(data);
List<ProviderInfo> providers =
data.createTypedArrayList(ProviderInfo.CREATOR);
ComponentName testName = (data.readInt() != 0)
? new ComponentName(data) : null;
ProfilerInfo profilerInfo = data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
Bundle testArgs = data.readBundle();
IBinder binder = data.readStrongBinder();
IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder);
binder = data.readStrongBinder();
IUiAutomationConnection uiAutomationConnection =
IUiAutomationConnection.Stub.asInterface(binder);
int testMode = data.readInt();
boolean openGlTrace = data.readInt() != 0;
boolean restrictedBackupMode = (data.readInt() != 0);
boolean persistent = (data.readInt() != 0);
Configuration config = Configuration.CREATOR.createFromParcel(data);
CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
HashMap<String, IBinder> services = data.readHashMap(null);
Bundle coreSettings = data.readBundle();
//[見流程3.11]
bindApplication(packageName, info, providers, testName, profilerInfo, testArgs,
testWatcher, uiAutomationConnection, testMode, openGlTrace,
restrictedBackupMode, persistent, config, compatInfo, services, coreSettings);
return true;
}
...
}
3.11 AT.bindApplication
[-> ActivityThread.java ::ApplicationThread]
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) {
if (services != null) {
//將services緩存起來, 減少binder檢索服務的次數
ServiceManager.initServiceCache(services);
}
//發送消息H.SET_CORE_SETTINGS
setCoreSettings(coreSettings);
IPackageManager pm = getPackageManager();
android.content.pm.PackageInfo pi = null;
try {
pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId());
} catch (RemoteException e) {
}
if (pi != null) {
boolean sharedUserIdSet = (pi.sharedUserId != null);
boolean processNameNotDefault = (pi.applicationInfo != null &&
!appInfo.packageName.equals(pi.applicationInfo.processName));
boolean sharable = (sharedUserIdSet || processNameNotDefault);
if (!sharable) {
VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir,
appInfo.processName);
}
}
//初始化AppBindData, 再發送消息H.BIND_APPLICATION
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}</code></pre>
其中setCoreSettings()過程就是調用sendMessage(H.SET_CORE_SETTINGS, coreSettings) 來向主線程發送SET_CORE_SETTINGS消息.bindApplication方法的主要功能是依次向主線程發送消息 H.SET_CORE_SETTINGS 和 H.BIND_APPLICATION . 接下來再來說說這兩個消息的處理過程
3.12 H.SET_CORE_SETTINGS
[-> ActivityThread.java ::H]
當主線程收到H.SET_CORE_SETTINGS,則調用handleSetCoreSettings
private void handleSetCoreSettings(Bundle coreSettings) {
synchronized (mResourcesManager) {
mCoreSettings = coreSettings;
}
onCoreSettingsChange();
}
private void onCoreSettingsChange() {
boolean debugViewAttributes = mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
if (debugViewAttributes != View.mDebugViewAttributes) {
View.mDebugViewAttributes = debugViewAttributes;
// 由于發生改變, 請求所有的activities重啟啟動
for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false);
}
}
}</code></pre>
3.13 H.BIND_APPLICATION
[-> ActivityThread.java ::H]
當主線程收到H.BIND_APPLICATION,則調用handleBindApplication
private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
...
//設置進程名
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());
if (data.persistent) {
//低內存設備, persistent進程不采用硬件加速繪制,以節省內存使用量
if (!ActivityManager.isHighEndGfx()) {
HardwareRenderer.disable(false);
}
}
//重置時區
TimeZone.setDefault(null);
Locale.setDefault(data.config.locale);
//更新系統配置
mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
mCurDefaultDisplayDpi = data.config.densityDpi;
applyCompatConfiguration(mCurDefaultDisplayDpi);
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
...
// 創建ContextImpl上下文
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
if (!Process.isIsolated()) {
final File cacheDir = appContext.getCacheDir();
if (cacheDir != null) {
System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
}
//用于存儲產生/編譯的圖形代碼
final File codeCacheDir = appContext.getCodeCacheDir();
if (codeCacheDir != null) {
setupGraphicsSupport(data.info, codeCacheDir);
}
}
final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
DateFormat.set24HourTimePref(is24Hr);
View.mDebugViewAttributes = mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
...
//當處于調試模式,則運行應用生成systrace信息
boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(appTracingAllowed);
//初始化 默認的http代理
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
}
if (data.instrumentationName != null) {
InstrumentationInfo ii = null;
ii = appContext.getPackageManager().getInstrumentationInfo(data.instrumentationName, 0);
mInstrumentationPackageName = ii.packageName;
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationSplitAppDirs = ii.splitSourceDirs;
mInstrumentationLibDir = ii.nativeLibraryDir;
mInstrumentedAppDir = data.info.getAppDir();
mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
mInstrumentedLibDir = data.info.getLibDir();
ApplicationInfo instrApp = new ApplicationInfo();
instrApp.packageName = ii.packageName;
instrApp.sourceDir = ii.sourceDir;
instrApp.publicSourceDir = ii.publicSourceDir;
instrApp.splitSourceDirs = ii.splitSourceDirs;
instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs;
instrApp.dataDir = ii.dataDir;
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
//通過反射,創建目標類
java.lang.ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
mInstrumentation.init(this, instrContext, appContext,
new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
data.instrumentationUiAutomationConnection);
...
} else {
mInstrumentation = new Instrumentation();
}
//FLAG_LARGE_HEAP則清除內存增長上限
if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
} else {
dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
}
try {
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
if (!data.restrictedBackupMode) {
List<ProviderInfo> providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
mInstrumentation.onCreate(data.instrumentationArgs);
//調用app.onCreate()方法.
mInstrumentation.callApplicationOnCreate(app);
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}</code></pre>
四. 總結
本文首先介紹AMS的4個同名不同參數的方法startProcessLocked; 緊接著講述了四大組件與進程的關系, Activity, Service, ContentProvider, BroadcastReceiver這四大組件,在啟動的過程,當其所承載的進程不存在時需要先創建進程. 再然后進入重點以startProcessLocked以引線一路講解整個過程所遇到的核心方法. 在整個過程中有新創建的進程與system_server進程之間的交互過程 是通過binder進行通信的, 這里有兩條binder通道分別為AMP/AMN 和 ATP/ATN.

上圖便是一次完整的進程創建過程,app的任何組件需要有一個承載其運行的容器,那就是進程, 那么進程的創建過程都是由系統進程system_server通過socket向zygote進程來請求fork()新進程, 當創建出來的app process與system_server進程之間的通信便是通過binder IPC機制.
來自:http://gityuan.com/2016/10/09/app-process-create-2/