編輯:Android資訊
Android系統將進程做得很友好的封裝,對於上層app開發者來說進程幾乎是透明的. 了解Android的朋友,一定知道Android四大組件,但對於進程可能會相對較陌生. 一個進程裡面可以跑多個app(通過share uid的方式), 一個app也可以跑在多個進程裡(通過配置Android:process屬性).
再進一步進程是如何創建的, 可能很多人不知道fork的存在. 在我的文章理解Android進程創建流程 集中一點詳細介紹了Process.start的過程是如何一步步創建進程.本文則是從另個角度來全局性講解Android進程啟動全過程所涉及的根脈, 先來看看AMS.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)
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 */);
}
小結:
Activity, Service, ContentProvider, BroadcastReceiver這四大組件,在啟動的過程,當其所承載的進程不存在時需要先創建進程. 這個創建進程的過程是調用前面講到的startProcessLocked方法1(a) . 調用流程: 1(a) => 1(b) ==> 2(b). 下面再簡單說說這4大組件與進程創建是在何時需要創建的.
啟動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);
}
啟動服務過程: 調用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) {
...
}
}
...
}
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);
}
...
}
廣播處理過程: 調用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) {
...
}
...
}
Activity, Service, ContentProvider, BroadcastReceiver這四大組件在啟動時,當所承載的進程不存在時,都需要創建. 進程的創建過程交由系統進程system_server來完成的.

簡稱:
圖解:
startProcessLocked方法,該方法最終通過socket方式,將需要創建新進程的消息告知Zygote進程,並阻塞等待Socket返回新創建進程的pid;system_server擁有ATP/AMS, 每一個新創建的進程都會有一個相應的AT/AMS,從而可以跨進程 進行相互通信. 這便是進程創建過程的完整生態鏈.
四大組件的進程創建時機:
前面剛已介紹四大組件的創建進程的過程是調用1(a) startProcessLocked方法,該方法會再調用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) {
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;
}
主要功能:
另外, 進程的uid是在進程真正創建之前調用newProcessRecordLocked方法來獲取的uid, 這裡會考慮是否為isolated的情況.
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
}
}
關於Process.start()是通過socket通信告知Zygote創建fork子進程,創建新進程後將ActivityThread類加載到新進程,並調用ActivityThread.main()方法。詳細過程見理解Android進程創建流程,接下來進入AT.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");
}
thread = new ActivityThread(): 該過程會初始化幾個很重要的變量:
H繼承於Handler;用於處理組件的生命周期.mH,這就是主線程的handler對象.之後主線程調用Looper.loop(),進入消息循環狀態, 當沒有消息時主線程進入休眠狀態, 一旦有消息到來則喚醒主線程並執行相關操作.
[-> 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) {
}
});
}
對於非系統attach的處理流程:
ApplicationThread[-> 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”
[-> 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;
}
}
}
[-> 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對象進行通信.
[-> 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;
}
}
//Broadcast: 檢查是否在這個進程中有下一個廣播接收者
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;
}
下面,再來說說thread.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過程.
[-> 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;
}
...
}
[-> 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);
}
其中setCoreSettings()過程就是調用sendMessage(H.SET_CORE_SETTINGS, coreSettings) 來向主線程發送SET_CORE_SETTINGS消息.bindApplication方法的主要功能是依次向主線程發送消息H.SET_CORE_SETTINGS和H.BIND_APPLICATION. 接下來再來說說這兩個消息的處理過程
[-> 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);
}
}
}
[-> ActivityThread.java ::H]
當主線程收到H.BIND_APPLICATION,則調用handleBindApplication
private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
...
//設置進程名, 也就是說進程名是在進程真正創建以後的BIND_APPLICATION過程中才取名
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對象,即在AndroidManifest.xml文件定義的應用名
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);
//調用Application.onCreate()回調方法.
mInstrumentation.callApplicationOnCreate(app);
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
小節: 到此進程啟動的全過程基本介紹完, 那接下來程序該往哪執行呢, 那就是要繼續看[見流程3.8] AMS.attachApplicationLocked.從[3.9 ~ 3.13] 只是介紹了bindApplication過程, 該方法之後便是組件啟動相關的內容,本文主要將進程相關內容, 組件的內容後續還會再進一步介紹.
本文首先介紹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機制.
谷歌官方 Android MVP 模式代碼解讀
關於Android程序的構架, 當前(2016.10)最流行的模式即為MVP模式, Google官方提供了Sample代碼來展示這種模式的用法. Repo地址:
Android 五大布局講解與應用
本文由碼農網 – 楊小勇原創,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃! Android總體有五大布局: 線性布局(LiearLayout)
Android為何比iOS卡?論1G內存的使用
昨天,一位認證信息為小米員工的網友在微博上發言,“iPhone 6 用戶都不在意 1G 內存不夠,紅米 2 的 1G 內存夠用了,保持流暢的秘訣就是少裝 App.
改變Android按鈕背景顏色的高效方法
本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃! 本文將介紹一種有效改變Android按鈕顏色的方法。 按鈕可以在狀