App启动流程分析
一.概述流程
在LAUNCH界面,点击一个app的图标之后,会调用startActivity来启动对应的Activity。
通过Binder远程通知AMS启动新的Activity。
AMS进行一系列的权限判断,创建ActivityRecord记录信息,Activity栈处理….等等一系列处理,最后会调用到startSpecificActivityLocked方法中。startSpecificActivityLocked方法中会进行判断,在进程没有启动的情况下,会调用startProcessLocked=>startProcessLocked=>Process.start()来启动一个进程。Process.start()是一个静态方法,他作为客户端会通过sockt与zygote进行通讯,Zygote作为服务端。Zygote通过JNI调用native方法fork一个它的子进程,并返回进程的pid。调用zygoteConnection的handleChildProc方法。关闭socoket,进行一些进程的设置,默认未捕捉异常的处理方法、时区的设置、重置log的配置,binder线程池和线程创建….通过反射来调用到ActivityThread的main方法,main方法中创建主线程Looper、并调用attach方法。通过Binder通讯调用AMS的attachApplicationLocked()方法,启动主线程Looper循环。跨进程调用ApplicationThread的bindApplication方法,通过Handler发送消息调用到ActivityThread的handleBindApplication方法,在这个方法中会完成创建Context的实现类ContextImpl对象、初始化Intrumentation对象、创建Application对象、装载Provider、调用Application的onCreate方法。调用到realStartActivityLocked,然后跨进程调用到applicationThread的scheduleLaunchActivity方法,scheduleLaunchActivity就会正真创建Activity。
二.具体流程分析
一 . 远程调用AMS中StartActivity
1.1 StartActivity
在Android中,当我们启动一个新的Activity或者service时,都是直接在Activity中调用StartActivity或者startService方法。这个方法最终会调用到startActivityForResult
public void startActivityForResult(@RequiresPermission Intent intent,
int requestCode,@Nullable Bundle options) {
if (mParent ==
null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken,
this,
intent, requestCode, options);
if (ar !=
null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >=
0) {
mStartedActivity =
true;
}
cancelInputsAndStartExitTransition(options);
}
else {
if (options !=
null) {
mParent.startActivityFromChild(
this, intent, requestCode, options);
}
else {
mParent.startActivityFromChild(
this, intent, requestCode);
}
}
}
其中:mMainThread的数据类型是ActivityThread,其中mMainThread.getApplicationThread()方法得到ApplicationThread;
1.2 execStartActivity
public ActivityResult
execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target, Intent intent,
int requestCode) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors !=
null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (
int i=
0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who,
null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >=
0 ? am.getResult() :
null;
}
break;
}
}
}
}
try {
intent.setAllowFds(
false);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
null,
0, token, target !=
null ? target.mEmbeddedID :
null,
requestCode,
false,
false,
null,
null,
false);
checkStartActivityResult(result, intent);
}
catch (RemoteException e) {
}
return null;
}
}
其中ActivityManagerNative.getDefault()会获得ActivityManagerService的本地代理对象ActivityManagerProxy, 调用ActivityManagerProxy.startActivity会通过Binder跨进程调用AMS中的startActivity方法;
二 Binder远程调用
2.1 ActivityManagerNative.getDefault().startActivity
public boolean onTransact(
int code, Parcel data, Parcel reply,
int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
Uri[] grantedUriPermissions = data.createTypedArray(Uri.CREATOR);
int grantedMode = data.readInt();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
boolean onlyIfNeeded = data.readInt() !=
0;
boolean debug = data.readInt() !=
0;
String profileFile = data.readString();
ParcelFileDescriptor profileFd = data.readInt() !=
0
? data.readFileDescriptor() :
null;
boolean autoStopProfiler = data.readInt() !=
0;
int result = startActivity(app, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler);
reply.writeNoException();
reply.writeInt(result);
return true;
}
三 AMS中具体启动流程
3.1 AMS.startActivity()
public final int startActivity(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho,
int requestCode,
boolean onlyIfNeeded,
boolean debug,
String profileFile, ParcelFileDescriptor profileFd,
boolean autoStopProfiler) {
return mMainStack.startActivityMayWait(caller, -
1, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
null,
null);
}
3.2 ActivityStack.startActivityMayWait()
直接调用了ActivityStack中的方法
final int startActivityMayWait(IApplicationThread caller,
int callingUid,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho,
int requestCode,
boolean onlyIfNeeded,
boolean debug, String profileFile, ParcelFileDescriptor profileFd,
boolean autoStopProfiler, WaitResult outResult, Configuration config) {
...
intent =
new Intent(intent);
ActivityInfo aInfo = resolveActivity(intent, resolvedType, debug,
profileFile, profileFd, autoStopProfiler);
...
ActivityContainer container = (ActivityContainer)iContainer;
synchronized (mService) {
int res = startActivityLocked(caller, intent, resolvedType,
grantedUriPermissions, grantedMode, aInfo,
resultTo, resultWho, requestCode, callingPid, callingUid,
onlyIfNeeded, componentSpecified,
null);
...
return res;
}
}
3.3 ActivityStack.startActivityLocked()
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType,
Uri[] grantedUriPermissions,
int grantedMode, ActivityInfo aInfo, IBinder resultTo,
String resultWho,
int requestCode,
int callingPid,
int callingUid,
boolean onlyIfNeeded,
boolean componentSpecified, ActivityRecord[] outActivity) {
int err = START_SUCCESS;
ProcessRecord callerApp =
null;
if (caller !=
null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp !=
null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
}
else {
Slog.w(TAG,
"Unable to find app for caller " + caller
+
" (pid=" + callingPid +
") when starting: "
+ intent.toString());
err = START_PERMISSION_DENIED;
}
}
if (err == START_SUCCESS) {
Slog.i(TAG,
"START {" + intent.toShortString(
true,
true,
true) +
"} from pid "
+ (callerApp !=
null ? callerApp.pid : callingPid));
}
ActivityRecord sourceRecord =
null;
ActivityRecord resultRecord =
null;
if (resultTo !=
null) {
int index = indexOfTokenLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(
TAG,
"Will send result to " + resultTo +
" (index " + index +
")");
if (index >=
0) {
sourceRecord = mHistory.get(index);
if (requestCode >=
0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
final int launchFlags = intent.getFlags();
if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) !=
0
&& sourceRecord !=
null) {
if (requestCode >=
0) {
return START_FORWARD_AND_REQUEST_CONFLICT;
}
resultRecord = sourceRecord.resultTo;
resultWho = sourceRecord.resultWho;
requestCode = sourceRecord.requestCode;
sourceRecord.resultTo =
null;
if (resultRecord !=
null) {
resultRecord.removeResultsLocked(
sourceRecord, resultWho, requestCode);
}
}
if (err == START_SUCCESS && intent.getComponent() ==
null) {
err = START_INTENT_NOT_RESOLVED;
}
if (err == START_SUCCESS && aInfo ==
null) {
err = START_CLASS_NOT_FOUND;
}
final int perm = mService.checkComponentPermission(aInfo.permission, callingPid,callingUid, aInfo.applicationInfo.uid, aInfo.exported);
...
ActivityRecord r =
new ActivityRecord(mService,
this, callerApp, callingUid,intent, resolvedType, aInfo, mService.mConfiguration,resultRecord, resultWho, requestCode, componentSpecified);
...
err = startActivityUncheckedLocked(r, sourceRecord,
grantedUriPermissions, grantedMode, onlyIfNeeded,
true);
if (mDismissKeyguardOnNextActivity && mPausingActivity ==
null) {
mDismissKeyguardOnNextActivity =
false;
mService.mWindowManager.dismissKeyguard();
}
return err;
}
主要是做权限检查,目标Activity信息的记录…等等
3.4 ActivityStack.startActivityUncheckedLocked
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
int grantedMode,
boolean onlyIfNeeded,
boolean doResume) {
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
int launchFlags = intent.getFlags();
...
startActivityLocked(r, newTask, doResume, keepCurTransition);
return START_SUCCESS;
}
这个方法中主要涉及了一些列的启动模式和Intent标志的处理,最后调用了与3.3小结中参数不同的startActivityLocked方法。
3.5 ActivityStack.startActivityLocked()
private final void startActivityLocked(ActivityRecord r,
boolean newTask,
boolean doResume,
boolean keepCurTransition) {
final int NH = mHistory.size();
int addPos = -
1;
if (!newTask) {
...
}
...
if (doResume) {
resumeTopActivityLocked(
null);
}
}
3.6 ActivityStack.resumeTopActivityLocked()
final boolean resumeTopActivityLocked(ActivityRecord prev) {
ActivityRecord next = topRunningActivityLocked(
null);
final boolean userLeaving = mUserLeaving;
mUserLeaving =
false;
if (next ==
null) {
if (mMainStack) {
return mService.startHomeActivityLocked();
}
}
next.delayedResume =
false;
if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
mService.mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
return false;
}
...
mStoppingActivities.remove(next);
mGoingToSleepActivities.remove(next);
next.sleeping =
false;
mWaitingVisibleActivities.remove(next);
if (mPausingActivity !=
null) {
if (DEBUG_SWITCH) Slog.v(TAG,
"Skip resume: pausing=" + mPausingActivity);
return false;
}
if (mResumedActivity !=
null) {
if (DEBUG_SWITCH) Slog.v(TAG,
"Skip resume: need to start pausing");
startPausingLocked(userLeaving,
false);
return true;
}
if (prev !=
null && prev != next) {
if (!prev.waitingVisible && next !=
null && !next.nowVisible) {
prev.waitingVisible =
true;
mWaitingVisibleActivities.add(prev);
if (DEBUG_SWITCH) Slog.v(
TAG,
"Resuming top, waiting visible to hide: " + prev);
}
else {
if (prev.finishing) {
mService.mWindowManager.setAppVisibility(prev.appToken,
false);
}
else {
...
}
}
}
...
if (prev !=
null) {
if (prev.finishing) {
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare close transition: prev=" + prev);
if (mNoAnimActivities.contains(prev)) {
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_NONE,
false);
}
else {
mService.mWindowManager.prepareAppTransition(prev.task == next.task? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: WindowManagerPolicy.TRANSIT_TASK_CLOSE,
false);
}
mService.mWindowManager.setAppWillBeHidden(prev.appToken);
mService.mWindowManager.setAppVisibility(prev.appToken,
false);
}
else {
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare open transition: prev=" + prev);
if (mNoAnimActivities.contains(next)) {
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_NONE,
false);
}
else {
mService.mWindowManager.prepareAppTransition(prev.task == next.task
? WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
: WindowManagerPolicy.TRANSIT_TASK_OPEN,
false);
}
}
if (
false) {
mService.mWindowManager.setAppWillBeHidden(prev.appToken);
mService.mWindowManager.setAppVisibility(prev.appToken,
false);
}
}
else if (mHistory.size() >
1) {
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare open transition: no previous");
if (mNoAnimActivities.contains(next)) {
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_NONE,
false);
}
else {
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN,
false);
}
}
if (next.app !=
null && next.app.thread !=
null) {
mService.mWindowManager.setAppVisibility(next.appToken,
true);
ActivityRecord lastResumedActivity = mResumedActivity;
ActivityState lastState = next.state;
mService.updateCpuStats();
next.state = ActivityState.RESUMED;
mResumedActivity = next;
next.task.touchActiveTime();
if (mMainStack) {
mService.addRecentTaskLocked(next.task);
}
mService.updateLruProcessLocked(next.app,
true,
true);
updateLRUListLocked(next);
boolean updated =
false;
if (mMainStack) {
synchronized (mService) {
Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
next.mayFreezeScreenLocked(next.app) ? next.appToken :
null);
if (config !=
null) {
next.frozenBeforeDestroy =
true;
}
updated = mService.updateConfigurationLocked(config, next,
false,
false);
}
}
if (!updated) {
ActivityRecord nextNext = topRunningActivityLocked(
null);
if (nextNext != next) {
mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
}
if (mMainStack) {
mService.setFocusedActivityLocked(next);
}
ensureActivitiesVisibleLocked(
null,
0);
mService.mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
return true;
}
try {
ArrayList a = next.results;
if (a !=
null) {
final int N = a.size();
if (!next.finishing && N >
0) {
next.app.thread.scheduleSendResult(next.appToken, a);
}
}
if (next.newIntents !=
null) {
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
}
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
System.identityHashCode(next),
next.task.taskId, next.shortComponentName);
next.sleeping =
false;
showAskCompatModeDialogLocked(next);
next.app.pendingUiClean =
true;
next.app.thread.scheduleResumeActivity(next.appToken,
mService.isNextTransitionForward());
checkReadyForSleepLocked();
}
catch (Exception e) {
...
startSpecificActivityLocked(next,
true,
false);
return true;
}
...
}
else {
if (!next.hasBeenLaunched) {
next.hasBeenLaunched =
true;
}
else {
if (SHOW_APP_STARTING_PREVIEW) {
mService.mWindowManager.setAppStartingWindow(
next.appToken, next.packageName, next.theme,
mService.compatibilityInfoForPackageLocked(
next.info.applicationInfo),
next.nonLocalizedLabel,
next.labelRes, next.icon, next.windowFlags,
null,
true);
}
if (DEBUG_SWITCH) Slog.v(TAG,
"Restarting: " + next);
}
startSpecificActivityLocked(next,
true,
true);
}
return true;
}
主要功能:
找不到需要resume的Activity,表示需要启动Launcher主界面。否则,需要执行startPausingLocked()来pause前一个Activity与WMS通讯,告知需要准备隐藏前一个Activity,准备显示其另一个Activity当目标进程中存在目标Activity,则跟新一系列的全局变量,resumeActivity;否则进入startSpecificActivityLocked环节
三. AMS中的最后一步
4.1 ActivityStack.startSpecificActivityLocked
private final void startSpecificActivityLocked(ActivityRecord r,
boolean andResume,
boolean checkConfig) {
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid);
if (r.launchTime ==
0) {
r.launchTime = SystemClock.uptimeMillis();
if (mInitialStartTime ==
0) {
mInitialStartTime = r.launchTime;
}
}
else if (mInitialStartTime ==
0) {
mInitialStartTime = SystemClock.uptimeMillis();
}
if (app !=
null && app.thread !=
null) {
try {
app.addPackage(r.info.packageName);
realStartActivityLocked(r, app, andResume, checkConfig);
return;
}
catch (RemoteException e) {
Slog.w(TAG,
"Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
mService.startProcessLocked(r.processName, r.info.applicationInfo,
true,
0,
"activity", r.intent.getComponent(),
false);
}
4.2 ProcessRecord.startProcessLocked()
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info,
boolean knownToBeDead,
int intentFlags,
String hostingType, ComponentName hostingName,
boolean allowWhileBooting) {
ProcessRecord app = getProcessRecordLocked(processName, info.uid);
...
String hostingNameStr = hostingName !=
null
? hostingName.flattenToShortString() :
null;
...
startProcessLocked(app, hostingType, hostingNameStr);
return (app.pid !=
0) ? app :
null;
}
4.3ProcessRecord.startProcessLocked()
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
...
try {
int uid = app.info.uid;
int[] gids =
null;
try {
gids = mContext.getPackageManager().getPackageGids(
app.info.packageName);
}
catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG,
"Unable to retrieve gids", e);
}
...
Process.ProcessStartResult startResult = Process.start(
"android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags,
app.info.targetSdkVersion,
null);
}
catch (RuntimeException e) {
app.pid =
0;
Slog.e(TAG,
"Failure starting process " + app.processName, e);
}
}
Process.start方法是一个静态方法可以直接调用
五. Process中与Zygote进程的通讯
5.1 Process.start
public static final ProcessStartResult
start(
final String processClass,
final String niceName,
int uid,
int gid,
int[] gids,
int debugFlags,
int targetSdkVersion,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, targetSdkVersion, zygoteArgs);
}
catch (ZygoteStartFailedEx ex) {
...
}
}
5.2 Process.startViaZygote
private static ProcessStartResult
startViaZygote(
final String processClass,
final String niceName,
final int uid,
final int gid,
final int[] gids,
int debugFlags,
int targetSdkVersion,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList<String> argsForZygote =
new ArrayList<String>();
argsForZygote.add(
"--runtime-init");
argsForZygote.add(
"--setuid=" + uid);
argsForZygote.add(
"--setgid=" + gid);
...
if (gids !=
null && gids.length >
0) {
StringBuilder sb =
new StringBuilder();
sb.append(
"--setgroups=");
int sz = gids.length;
for (
int i =
0; i < sz; i++) {
if (i !=
0) {
sb.append(
',');
}
sb.append(gids[i]);
}
argsForZygote.add(sb.toString());
}
if (niceName !=
null) {
argsForZygote.add(
"--nice-name=" + niceName);
}
argsForZygote.add(processClass);
if (extraArgs !=
null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
return zygoteSendArgsAndGetResult(argsForZygote);
}
}
该过程主要工作是生成argsForZygote容器,保存了进程的uid、gid、groups、target-sdk、nice-name等一系列的参数。
5.3 Process.zygoteSendArgsAndGetResult
private static ProcessStartResult
zygoteSendArgsAndGetResult(ArrayList<String> args)
throws ZygoteStartFailedEx {
openZygoteSocketIfNeeded();
try {
sZygoteWriter.write(Integer.toString(args.size()));
sZygoteWriter.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");
}
sZygoteWriter.write(arg);
sZygoteWriter.newLine();
}
sZygoteWriter.flush();
ProcessStartResult result =
new ProcessStartResult();
result.pid = sZygoteInputStream.readInt();
if (result.pid <
0) {
throw new ZygoteStartFailedEx(
"fork() failed");
}
result.usingWrapper = sZygoteInputStream.readBoolean();
return result;
}
catch (IOException ex) {
try {
if (sZygoteSocket !=
null) {
sZygoteSocket.close();
}
}
catch (IOException ex2) {
Log.e(LOG_TAG,
"I/O exception on routine close", ex2);
}
sZygoteSocket =
null;
throw new ZygoteStartFailedEx(ex);
}
}
在调用openZygoteSocketIfNeeded之后会建立与Zytote进程的Socket通道
5.3 Process.openZygoteSocketIfNeeded
private static void openZygoteSocketIfNeeded()
throws ZygoteStartFailedEx {
int retryCount;
if (sPreviousZygoteOpenFailed) {
retryCount =
0;
}
else {
retryCount =
10;
}
for (
int retry =
0; (sZygoteSocket ==
null) && (retry < (retryCount +
1)); retry++ ) {
if (retry >
0) {
try {
Log.i(
"Zygote",
"Zygote not up yet, sleeping...");
Thread.sleep(ZYGOTE_RETRY_MILLIS);
}
catch (InterruptedException ex) {
}
}
try {
sZygoteSocket =
new LocalSocket();
sZygoteSocket.connect(
new LocalSocketAddress(ZYGOTE_SOCKET,
LocalSocketAddress.Namespace.RESERVED));
sZygoteInputStream
=
new DataInputStream(sZygoteSocket.getInputStream());
sZygoteWriter =
new BufferedWriter(newOutputStreamWriter(sZygoteSocket.getOutputStream()),
256);
sPreviousZygoteOpenFailed =
false;
break;
}
catch (IOException ex) {
if (sZygoteSocket !=
null) {
try {
sZygoteSocket.close();
}
catch (IOException ex2) {
Log.e(LOG_TAG,
"I/O exception on close after exception",
ex2);
}
}
sZygoteSocket =
null;
}
}
if (sZygoteSocket ==
null) {
sPreviousZygoteOpenFailed =
true;
throw new ZygoteStartFailedEx(
"connect failed");
}
}
这个方法的主要作用就是创建Socket,然后唤醒Zygote进程,并连接Zygote进程端。
六. Zygote进程fork子进程
Zygote进程是init进程fork的子进程,进程启动之后调用ZygoteInit.main()方法,经过创建socket管道,预加载资源后,最后调用runSelectLoop()方法。
6.1 ZygoteInit.runSelectLoopMode
private static void runSelectLoopMode()
throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds =
new ArrayList();
ArrayList<ZygoteConnection> peers =
new ArrayList();
FileDescriptor[] fdArray =
new FileDescriptor[
4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(
null);
int loopCount = GC_LOOP_COUNT;
while (
true) {
int index;
if (loopCount <=
0) {
gc();
loopCount = GC_LOOP_COUNT;
}
else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
}
catch (IOException ex) {
throw new RuntimeException(
"Error in select()", ex);
}
if (index <
0) {
throw new RuntimeException(
"Error in select()");
}
else if (index ==
0) {
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
}
else {
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
客户端通过openZygoteSocketIfNeeded()与zygote进程建立连接。zygote进程收到客户端连接请求后执行accept();然后再创建ZygoteConnection对象,并添加到fds容器中;建立连接之后,可以跟客户端通信,进入runOnce()方法来接收客户端数据,并执行进程创建工作。
6.2 ZygoteInit.acceptCommandPeer
private static ZygoteConnection
acceptCommandPeer() {
try {
return new ZygoteConnection(sServerSocket.accept());
}
catch (IOException ex) {
throw new RuntimeException(
"IOException during accept()", ex);
}
}
6.3 ZygoteConnection.runOnce
boolean runOnce()
throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs =
null;
FileDescriptor[] descriptors;
try {
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
}
catch (IOException ex) {
Log.w(TAG,
"IOException on command socket " + ex.getMessage());
closeSocket();
return true;
}
if (args ==
null) {
closeSocket();
return true;
}
/** the stderr of the most recent request, if avail */
PrintStream newStderr =
null;
if (descriptors !=
null && descriptors.length >=
3) {
newStderr =
new PrintStream(
new FileOutputStream(descriptors[
2]));
}
int pid = -
1;
FileDescriptor childPipeFd =
null;
FileDescriptor serverPipeFd =
null;
try {
parsedArgs =
new Arguments(args);
...
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, parsedArgs.debugFlags, rlimits);
}
catch (IOException ex) {
logAndPrintError(newStderr,
"Exception creating pipe", ex);
}
catch (ErrnoException ex) {
logAndPrintError(newStderr,
"Exception creating pipe", ex);
}
catch (IllegalArgumentException ex) {
logAndPrintError(newStderr,
"Invalid zygote arguments", ex);
}
catch (ZygoteSecurityException ex) {
logAndPrintError(newStderr,
"Zygote security policy prevents request: ", ex);
}
try {
if (pid ==
0) {
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd =
null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
}
else {
IoUtils.closeQuietly(childPipeFd);
childPipeFd =
null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
}
finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
6.3 Zygote.forkAndSpecialize
public static int forkAndSpecialize(
int uid,
int gid,
int[] gids,
int debugFlags,
int[][] rlimits) {
preFork();
int pid = nativeForkAndSpecialize(uid, gid, gids, debugFlags, rlimits);
postFork();
return pid;
}
native public static int nativeForkAndSpecialize(
int uid,
int gid,
int[] gids,
int debugFlags,
int[][] rlimits);
6.4 ZygoteConnection.handleChildProc
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
if (parsedArgs.peerWait) {
try {
ZygoteInit.setCloseOnExec(mSocket.getFileDescriptor(),
true);
sPeerWaitSocket = mSocket;
}
catch (IOException ex) {
Log.e(TAG,
"Zygote Child: error setting peer wait "
+
"socket to be close-on-exec", ex);
}
}
else {
closeSocket();
ZygoteInit.closeServerSocket();
}
...
if (parsedArgs.niceName !=
null) {
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith !=
null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
pipeFd, parsedArgs.remainingArgs);
}
else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs);
}
}
else {
String className;
try {
className = parsedArgs.remainingArgs[
0];
}
catch (ArrayIndexOutOfBoundsException ex) {
logAndPrintError(newStderr,
"Missing required class name argument",
null);
return;
}
String[] mainArgs =
new String[parsedArgs.remainingArgs.length -
1];
System.arraycopy(parsedArgs.remainingArgs,
1,
mainArgs,
0, mainArgs.length);
if (parsedArgs.invokeWith !=
null) {
WrapperInit.execStandalone(parsedArgs.invokeWith,
parsedArgs.classpath, className, mainArgs);
}
else {
ClassLoader cloader;
if (parsedArgs.classpath !=
null) {
cloader =
new PathClassLoader(parsedArgs.classpath,
ClassLoader.getSystemClassLoader());
}
else {
cloader = ClassLoader.getSystemClassLoader();
}
try {
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
}
catch (RuntimeException ex) {
logAndPrintError(newStderr,
"Error starting.", ex);
}
}
}
}
6.5 RuntimeInit.zygoteInit
public static final void zygoteInit(
int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG,
"RuntimeInit: Starting application from zygote");
redirectLogStreams();
commonInit();
zygoteInitNative();
applicationInit(targetSdkVersion, argv);
}
6.6 RuntimeInit.commonInit
private static final void commonInit() {
Thread.setDefaultUncaughtExceptionHandler(
new UncaughtHandler());
int hasQwerty = getQwertyKeyboard();
if (DEBUG) Slog.d(TAG,
">>>>> qwerty keyboard = " + hasQwerty);
if (hasQwerty ==
1) {
System.setProperty(
"qwerty",
"1");
}
TimezoneGetter.setInstance(
new TimezoneGetter() {
@Override
public String
getId() {
return SystemProperties.get(
"persist.sys.timezone");
}
});
TimeZone.setDefault(
null);
LogManager.getLogManager().reset();
new AndroidConfig();
String userAgent = getDefaultUserAgent();
System.setProperty(
"http.agent", userAgent);
NetworkManagementSocketTagger.install();
String trace = SystemProperties.get(
"ro.kernel.android.tracing");
if (trace.equals(
"1")) {
Slog.i(TAG,
"NOTE: emulator trace profiling enabled");
Debug.enableEmulatorTraceOutput();
}
initialized =
true;
}
一些通用的初始化
6.7 RuntimeInit.zygoteInitNative()
static void
com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->
onZygoteInit();
}
6.7.1 app_main.onZygoteInit
virtual
void onZygoteInit()
{
sp
<ProcessState
> proc
= ProcessState
::self();
proc
->startThreadPool();
}
6.8 RuntimeInit.applicationInit
private static void applicationInit(
int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
VMRuntime.getRuntime().setTargetHeapUtilization(
0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args =
new Arguments(argv);
}
catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
return;
}
invokeStaticMain(args.startClass, args.startArgs);
}
6.9 RuntimeInit.invokeStaticMain
private static void invokeStaticMain(String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className);
}
catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod(
"main",
new Class[] { String[].class });
}
catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
}
catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
7.1
public static void main(String[] args) {
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(
false);
Process.setArgV0(
"<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler ==
null) {
sMainThreadHandler =
new Handler();
}
ActivityThread thread =
new ActivityThread();
thread.attach(
false);
if (
false) {
Looper.myLooper().setMessageLogging(
new
LogPrinter(Log.DEBUG,
"ActivityThread"));
}
Looper.loop();
throw new RuntimeException(
"Main thread loop unexpectedly exited");
}
此时,就直接调用到了我们熟悉的ActivityThread中main方法。 App启动流程分析 (下)