前言
啟動(dòng)一個(gè)Android組件時(shí)冻辩,當(dāng)App進(jìn)程還不存在蛋铆,應(yīng)先創(chuàng)建一個(gè)App進(jìn)程。追蹤Ams源碼诗芜,在棧監(jiān)管者startSpecificActivityLocked方法中有判斷進(jìn)程是否存在瞳抓。
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
.....
if (app != null && app.thread != null) {
...//進(jìn)程存在
realStartActivityLocked()
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
Ams#getProcessRecordLocked方法查找進(jìn)程ProcessRecord記錄秒紧。若未找到,創(chuàng)建進(jìn)程 挨下。
當(dāng)用戶第一次點(diǎn)擊App圖標(biāo),系統(tǒng)啟動(dòng)App的AndroidManifest中配置action為android.intent.action.MAIN的Activity組件脐湾。
ActivityStackSupervisor#startActivityMayWait方法臭笆。
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,..) {
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException
("File descriptors passed in Intent");
}
boolean componentSpecified = intent.getComponent() != null;
// Don't modify the client's object!
intent = new Intent(intent);
// Collect information about the target of the Intent.
// 搜集目標(biāo)Intent的信息
ActivityInfo aInfo =resolveActivity(intent, resolvedType, startFlags,
profilerInfo, userId);
...
}
棧監(jiān)管者resolveActivity方法解析Intent信息。注意秤掌,這是啟動(dòng)App第一個(gè)Activity組件愁铺,App進(jìn)程還未創(chuàng)建。
ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
ProfilerInfo profilerInfo, int userId) {
ActivityInfo aInfo;
try {
//AppGlobals獲取包管理器IPackageManager闻鉴。
ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
| ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
} catch (RemoteException e) {
aInfo = null;
}
if (aInfo != null) {
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
...
}
return aInfo;
}
從ActivityThread#getPackageManager*獲取包管理器茵乱,
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
return sPackageManager;
}
//從ServiceManager獲取包服務(wù),僅初始化一次孟岛。
IBinder b = ServiceManager.getService("package");
//代理
sPackageManager = IPackageManager.Stub.asInterface(b);
return sPackageManager;
}
包管理器Pms#resolveIntent方法瓶竭,解析Intent,返回ResolveInfo渠羞。主要結(jié)構(gòu)包含ActivityInfo斤贰,ActivityInfo結(jié)構(gòu)圖。進(jìn)程名processName次询,ActivityInfo內(nèi)部有一個(gè)ApplicationInfo對(duì)象荧恍。
進(jìn)程創(chuàng)建
進(jìn)程創(chuàng)建流程圖。下面是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) {
ProcessRecord app;
if (!isolated) {//非孤立
//根據(jù)進(jìn)程名查詢進(jìn)程記錄ProcessRecord
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
...
} else {
//當(dāng)用戶顯式啟動(dòng)進(jìn)程時(shí)送巡,清除其崩潰計(jì)數(shù)
mProcessCrashTimes.remove(info.processName, info.uid);
...
}
} else {
// 如果是孤立進(jìn)程,無法重用存在的進(jìn)程
app = null;
}
//如果app不空,說明存在進(jìn)程記錄盒卸,調(diào)用者不認(rèn)為該進(jìn)程已經(jīng)死掉或者沒有線程對(duì)象骗爆,
//pid存在
if (app != null && app.pid > 0) {
if (!knownToBeDead || app.thread == null) {
//app已經(jīng)開始運(yùn)行,則加入新包,返回ProcessRecord
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: done, added package to proc");
return app;
}
//app記錄綁定了以前的進(jìn)程蔽介。清理淮腾,需要啟動(dòng)進(jìn)程
killProcessGroup(app.info.uid, app.pid);
handleAppDiedLocked(app, true, true);
}
if (app == null) {
//創(chuàng)建ProcessRecord
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
return null;
}
app.crashHandler = crashHandler;
} else {
// ProcessRecord存在,則加入新包
app.addPackage(info.packageName, info.versionCode, mProcessStats);
}
//創(chuàng)建進(jìn)程屉佳,Ams#startProcessLocked方法谷朝。
startProcessLocked(app, hostingType, hostingNameStr, abiOverride,
entryPoint, entryPointArgs);
return (app.pid != 0) ? app : null;
}
創(chuàng)建ProcessRecord,它當(dāng)?shù)膒id是0武花,startProcessLocked啟動(dòng)進(jìn)程圆凰。
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint,
String[] entryPointArgs) {
...
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
...
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);
...
}
設(shè)置entryPoint為android.app.ActivityThread,ActivityThread類的main方法的是新進(jìn)程App啟動(dòng)入口体箕。
Process的start方法专钉,向zygote進(jìn)程發(fā)送創(chuàng)建新進(jìn)程的請(qǐng)求挑童,啟動(dòng)成功的結(jié)果是ProcessStartResult中包含新進(jìn)程pid。
Process#startViaZygote方法跃须,創(chuàng)建一個(gè)字符串參數(shù)列表站叼,調(diào)用Process#zygoteSendArgsAndGetResult方法,將參數(shù)列表發(fā)送給zygote進(jìn)程菇民。zygote進(jìn)程收到后尽楔,啟動(dòng)一個(gè)子進(jìn)程,將子進(jìn)程pid返回第练。
startViaZygote方法參數(shù)圖阔馋。
private static ProcessStartResult startViaZygote(...String[] extraArgs)
throws ZygoteStartFailedEx {
return zygoteSendArgsAndGetResult(
openZygoteSocketIfNeeded(abi), argsForZygote);
}
Process#openZygoteSocketIfNeeded方法,利用ZygoteState#connect返回ZygoteState娇掏。
private static ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed");
}
writer.write(arg);
writer.newLine();
}
writer.flush();
ProcessStartResult result = new ProcessStartResult();
//讀取返回的pid
result.pid = inputStream.readInt();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = inputStream.readBoolean();
return result;
} catch (IOException ex) {
}
}
Process保存主ZygoteState和次ZygoteState兩個(gè)靜態(tài)對(duì)象呕寝,代表兩個(gè)與zygote進(jìn)程的socket連接。當(dāng)主ZygoteState連接可用婴梧,則直接使用下梢,否則利用次ZygoteState,若都不可用塞蹭,拋出異常怔球。
通過socket與zygote進(jìn)程通信,連接與數(shù)據(jù)流讀寫鏈路封裝在ZygoteState浮还。主ZygoteState定義的連接地址名稱是zygote竟坛,次ZygoteState定義的連接地址名稱是zygote_secondary。
BufferedWriter和DataInputStream數(shù)據(jù)流钧舌,發(fā)送和讀取担汤。
與zygote進(jìn)程Socket通信
與zygote進(jìn)程的Socket通信結(jié)構(gòu)圖。創(chuàng)建ZygoteState的connect方法洼冻。
public static ZygoteState connect(String socketAddress) throws IOException {
DataInputStream zygoteInputStream = null;
BufferedWriter zygoteWriter = null;
final LocalSocket zygoteSocket = new LocalSocket();
try {
//到zygote進(jìn)程的socket連接
zygoteSocket.connect(new LocalSocketAddress(socketAddress,
LocalSocketAddress.Namespace.RESERVED));
//建立讀寫數(shù)據(jù)通道
zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
zygoteWriter = new BufferedWriter(new OutputStreamWriter(
zygoteSocket.getOutputStream()), 256);
} catch (IOException ex) {
//socket關(guān)閉崭歧,拋出異常
}
....
return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
Arrays.asList(abiListString.split(",")));
}
1.創(chuàng)建LocalSocket,委托LocalSocketImpl實(shí)現(xiàn)類撞牢,利用LocalSocketImpl的文件描述符FileDescriptor建立連接率碾。
2.建立讀寫數(shù)據(jù)通道,創(chuàng)建ZygoteState對(duì)象屋彪,封裝通道與連接所宰。
LocalSocket#connect方法。
public void connect(LocalSocketAddress endpoint) throws IOException {
synchronized (this) {
implCreateIfNeeded();//初始化連接描述符
impl.connect(endpoint, 0);
isConnected = true;
isBound = true;
}
}
建立連接畜挥。implCreateIfNeeded方法仔粥,通過LocalSocketImpl#create方法初始化連接描述符Fd。
利用Os.socket(OsConstants.AF_UNIX, osType, 0)。
委托LocalSocketImpl#connect方法躯泰。
protected void connect(LocalSocketAddress address, int timeout)
throws IOException{
if (fd == null) {//Fd已在implCreateIfNeeded初始化谭羔。
throw new IOException("socket not created");
}
connectLocal(fd, address.getName(), address.getNamespace().getId());
}
JNI#方法進(jìn)行連接,address就是上面提到過的主ZygoteState定義的zygote麦向。
LocalSocket#getInputStream方法瘟裸,getOutputStream方法委托LocalSocketImpl的方法創(chuàng)建讀寫數(shù)據(jù)流,SocketInputStream與SocketOutputStream诵竭,數(shù)據(jù)流封裝在LocalSocketImpl话告。
數(shù)據(jù)流返回后,再次封裝秀撇,BufferedWriter與DataInputStream。
本質(zhì):BufferedWriter#write向族,利用SocketOutputStream向Fd發(fā)送數(shù)據(jù)呵燕,DataInputStream#read,利用SocketInputStream從Fd讀取數(shù)據(jù)件相。
最后再扭,進(jìn)程創(chuàng)建成功,pid保存在ProcessStartResult夜矗。
App入口方法
ActivityThread的main方法是新進(jìn)程入口泛范。
public static void main(String[] args) {
.....
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
//ActivityThread內(nèi)部H對(duì)象,負(fù)責(zé)處理主線程消息紊撕,如AMS罢荡,WMS利用Binder發(fā)來的消息。
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
初始化主線程消息隊(duì)列对扶,啟用主線程Looper区赵,等待消息,創(chuàng)建ActivityThread對(duì)象浪南,觸發(fā)ActivityThread#attach方法笼才。
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
//mAppThread是ApplicationThread類型
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
...
} else {
...
}
}
非系統(tǒng)應(yīng)用時(shí),Ams#attachApplication方法络凿,Ams利用ApplicationThread訪問App進(jìn)程骡送,這是剛創(chuàng)建的進(jìn)程,此時(shí)主線程消息隊(duì)列已經(jīng)創(chuàng)建絮记,可向隊(duì)列插入消息摔踱,但Loop循環(huán)還未起來。
Ams#attachApplicationLocked方法中怨愤,先ApplicationThread#bindApplication回調(diào)App進(jìn)程昌渤,向主線程消息隊(duì)列發(fā)送BIND_APPLICATION消息,待Looper起來后憔四,就會(huì)執(zhí)行啦膀息。
后續(xù)般眉,還會(huì)觸發(fā)ActivityStackSupervisor#attachApplicationLocked方法潜支,進(jìn)入realStartActivityLocked方法,它就是剛開篇介紹過的,進(jìn)程存在時(shí)代碼執(zhí)行的選擇,在realStartActivityLocked繼續(xù)往下走,啟動(dòng)Activity組件。
總結(jié)
創(chuàng)建App進(jìn)程的核心知識(shí)點(diǎn)是建立一個(gè)與zygote進(jìn)程通信的Socket連接,通過向其發(fā)送參數(shù)大审,請(qǐng)求zygote創(chuàng)建App進(jìn)程根穷。
任重而道遠(yuǎn)