Android6.0之AMS启动app中篇之创建app进程
来源:互联网 发布:程序员怎么在北京生活 编辑:程序博客网 时间:2024/06/05 10:22
前面分析到了ActivityStackSupervisor类中的startActivityUncheckedLocked方法,该方法主要是为要启动的activity准备一个task:有可复用的task,就直接使用;没有的话,就先寻找一个合适的ActivityStack,移动到前台后创建一个新的Task.紧接着调用ActivityStack的startActivityLocked()方法继续启动.
ActivityStack的startActivityLocked()
首先分析参数:
123456
final void startActivityLocked(ActivityRecord r, // 要启动的activityboolean newTask,//是否新建了task,传入的trueboolean doResume,// 是否执行resume,传入的trueboolean keepCurTransition,// 传入的fasle,当要从一个activity启动一个activity,而且启动这个activity时,设置了FLAG_ACTIVITY_CLEAR_TOP,传入trueBundle options)
如果是新创建的task,这个task已经在ActivityStack的顶端,而且其所在的Activitystack也在绑定的屏幕的顶端:
123456789101112
// r.task就是在startActivityUncheckedLocked中创建的新的task的TaskRecord对象,取出来保存到rRask变量中TaskRecord rTask = r.task;final int taskId = rTask.taskId;// 如果是新创建的task的话// taskForIdLocked在历史栈中查询是否含有id号为目标类所在的栈id,如果有,表明目标类之前已经被创建过,现在开始复用该对象,属于非首次启动,// newTask传递过来为trueif (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) { // 将其移到activitystack的顶部,也就是mTaskHistory的尾部 insertTaskAtTop(rTask, r); mWindowManager.moveTaskToTop(taskId);}
如果不需要新创建task:(从launcher第一次启动app,会创建新的task,所以不走这块代码)
123456789101112131415161718192021222324
TaskRecord task = null;if (!newTask) { boolean startIt = true; // 从 mTaskHistory中找到启动这个activity的activity所在的task for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { task = mTaskHistory.get(taskNdx); if (task.getTopActivity() == null) { // All activities in task are finishing. continue; } // 找到了 if (task == r.task) { if (!startIt) { ............ ActivityOptions.abort(options); return; } break; }// 如果在前面的task中有全屏应用存在,例如播放器等,设置为false. else if (task.numFullscreen > 0) { startIt = false; } }}
上面代码就是从activitystack的mTaskHistory中找到启动这个activity的activity的task.
如果找到的这个task不在ActivityStack的顶端,那就没必要让当前正在显示的activity执行onUserLeaving操作.
12345
if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) { mStackSupervisor.mUserLeaving = false; if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, "startActivity() behind front, mUserLeaving=false"); }
接着把要启动的activity放入Task的顶端,并设置inHistory为true;
1234
task = r.task;task.addActivityToTop(r);task.setFrontOfTask();r.putInHistory();
下面WMS开始准备绘制activity以及切换Activity时的动画.略过:
1234567891011121314151617181920212223
if (!isHomeStack() || numActivities() > 0){ ... // 一个activity的UI界面要想再终端屏幕上显示出来,很重要的一点就是他必须向WMS中添加token,以便于WMS在启动窗口的时候能够找到它 mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind); boolean doShow = true; if (newTask) { if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { // 处理FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,rest task resetTaskIfNeededLocked(r, r); // 得到rest task之后,task的顶端activity是否与要启动的activity一致 doShow = topRunningNonDelayedActivityLocked(null) == r; } } else if (options != null && new ActivityOptions(options).getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) { doShow = false; } ...}else{}
上述代码中关键的一点是:当是新创建task的时候,此时这个task的affinity就是activity的taskAffinity.这个要启动activity就是这个task的root activity.
这时候如果flag中包含FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,那么就会寻找当前activitystack中所有task中是设置了允许TaskReparenting,而又与其启动者没有依赖关系的activity(activity的resultTo为空),查看他们指定的task是不是现在这个新创建的task,是的话移动到这个新创建的task中来.
Task的startActivityLocked()方法主要就是将要启动的Activity加入到task的顶部.如果传入的newTask为true,表明创建了新的task,这是还要检查是否进行rest task操作处理TaskReparenting;为false,表明没有创建task,而是将activity加入到启动他的activity所在的task中.然后把task调整到ActivityStack中的mTaskHistory的顶部.也就是将task移动到栈顶.然后调用
1234
// 传入的为trueif (doResume) { mStackSupervisor.resumeTopActivitiesLocked(this, r, options); }
开始显示task顶部的activity(并不一定是要启动的activity).
ActivityStackSupervisor.resumeTopActivitiesLocked()方法
这里要说明下,当从launcher,也就是桌面切换到一个app的activity的时候,前面也说了如果这个app所在的activitystack和homestack处于同一个屏幕中,就要调用ActivityStackSupervisor.moveHomeStack方法,来移动homestack.(确切的是当调用Activitystack.moveToFront()方法时,会进行这样的操作.)这时,mFocusedStack就会发生变化了,之前mFocusedStack是mhomeStack.在moveHomeStack方法会将其设置为即将显示的activity所在的ActivityStack.
12345678910111213141516
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions) { // 如果传入的ActivityStack为null,那么设置为当前处于前台的ActivityStack if (targetStack == null) { targetStack = mFocusedStack; } // Do targetStack first. boolean result = false; // 检查targetStack是否和mFocusedStack一致.这里是一致的.原因前面解释了. if (isFrontStack(targetStack)) { result = targetStack.resumeTopActivityLocked(target, targetOptions); } ............ return result; }
ActivityStack.resumeTopActivityLocked()方法
123456789101112131415161718192021
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { // 如果当前正在resume顶端activity的话,那就直接返回false if (mStackSupervisor.inResumeTopActivity) { // Don't even start recursing. return false; } boolean result = false; try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) { mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN; mService.updateSleepIfNeededLocked(); } result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } return result;}
实际上是调用resumeTopActivityInnerLocked()方法
ActivityStack.resumeTopActivityInnerLocked
方法代码又是很多……….看注释吧!
123456789101112131415
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) { if (DEBUG_LOCKSCREEN) mService.logLockScreen(""); if (!mService.mBooting && !mService.mBooted) { // Not ready yet! return false; } ActivityRecord parent = mActivityContainer.mParentActivity; if ((parent != null && parent.state != ActivityState.RESUMED) || !mActivityContainer.isAttachedLocked()) { // Do not resume this stack if its parent is not resumed. // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st. return false; }
这里的操作还是比较简单的,首先查看系统是否启动完成了,否则就直接返回。如果启动当前activity的activity本身的状态不是RESUMED的话,那么不能启动activity,直接返回false。
接下来找到,要启动的activity,这里实际上就是task的顶端activity.经过前面的过程,当前前台的task的就是运行要启动的activity所需的task.但至于顶端是否是要启动的activity那就不一定了.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
// next就是要启动的activityfinal ActivityRecord next = topRunningActivityLocked(null);final boolean userLeaving = mStackSupervisor.mUserLeaving;mStackSupervisor.mUserLeaving = false;// prevTask就是要启动的activity所在的taskfinal TaskRecord prevTask = prev != null ? prev.task : null;// 没有要启动的activity,那就显示homeif (next == null) { .... ....}// 不需要延时resumenext.delayedResume = false;// If the top activity is the resumed one, nothing to do.// 如果显示的activity就是要启动的activity,那么直接返回falseif (mResumedActivity == next && next.state == ActivityState.RESUMED && mStackSupervisor.allResumedActivitiesComplete()) { ............ return false;}// 下面又是做了一些检查而已// 其中在创建task的时候// taskType = APPLICATION_ACTIVITY_TYPE;// mTaskToReturnTo = HOME_ACTIVITY_TYPE;// 所以isOverHomeStack返回trueif (prevTask != null && prevTask.stack == this && prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) { if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); // 几乎都满足这个条件,而setFrontOfTask前面已经做过了 if (prevTask == nextTask) { prevTask.setFrontOfTask(); } else if (prevTask != topTask()) { // This task is going away but it was supposed to return to the home stack. // Now the task above it has to return to the home task instead. // 如果task销毁了,移动到home final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE); } else if (!isOnHomeDisplay()) { return false; } else if (!isHomeStack()){ .............. }}
接下来还是做检查:如果系统当前准备休眠或者关机,如果是的话,那么就放弃本次启动。
123456789101112131415
// If we are sleeping, and there is no resumed activity, and the top// activity is paused, well that is the state we want.if (mService.isSleepingOrShuttingDown() && mLastPausedActivity == next && mStackSupervisor.allPausedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. mWindowManager.executeAppTransition(); mNoAnimActivities.clear(); ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Going to sleep and all paused"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false;}
还是做检查,检查这个activity的用户已经启动了.
12345678910111213141516
// Make sure that the user who owns this activity is started. If not,// we will just leave it as is because someone should be bringing// another user's activities to the top of the stack.if (mService.mStartedUsers.get(next.userId) == null) { Slog.w(TAG, "Skipping resume of top activity " + next + ": user " + next.userId + " is stopped"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return false;}// The activity may be waiting for stop, but that is no longer// appropriate for it.mStackSupervisor.mStoppingActivities.remove(next);mStackSupervisor.mGoingToSleepActivities.remove(next);next.sleeping = false;mStackSupervisor.mWaitingVisibleActivities.remove(next);
如果当前启动的activity正在等待stop,那么就放弃stop直接启动。因为现在已经没有必要将它stop了。
如果我们当前正在pause一个activity,那么我们需要等到我们的pause动作完成了才能开始启动activity。
12345678910111213141516171819202122
// We need to start pausing the current activity so the top one // can be resumed... boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0; boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause); if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause); } if (pausing) { if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES, "resumeTopActivityLocked: Skip resume: need to start pausing"); // At this point we want to put the upcoming activity's process // at the top of the LRU list, since we know we will be needing it // very soon and it would be a waste to let it get killed if it // happens to be sitting towards the end. if (next.app != null && next.app.thread != null) { mService.updateLruProcessLocked(next.app, true, null); } if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; }
继续,如果activity所在的app进程已经启动,那么直接显示activity.
123456789101112131415161718192021222324252627282930313233343536373839404142434445
ActivityStack lastStack = mStackSupervisor.getLastStack(); if (next.app != null && next.app.thread != null){ if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next); // This activity is now becoming visible. mWindowManager.setAppVisibility(next.appToken, true); .......... mService.updateCpuStats(); .......... try { //这个activity还有等待返回的结果,先发送结果 ArrayList<ResultInfo> a = next.results; if (a != null) { final int N = a.size(); if (!next.finishing && N > 0) { if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a); next.app.thread.scheduleSendResult(next.appToken, a); } } // 此时,说明要启动的activity已经存在,直接回调应用的onNewIntent方法 if (next.newIntents != null) { next.app.thread.scheduleNewIntent(next.newIntents, next.appToken); } ............ //调用activity的onResume next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState, mService.isNextTransitionForward(), resumeAnimOptions); mStackSupervisor.checkReadyForSleepLocked(); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next); } catch (Exception e) { .............. } ............. }else{ // 如过activity所在的进程还没启动,那么就使用下面的方法启动app进程. mStackSupervisor.startSpecificActivityLocked(next, true, true); }
resumeTopActivityInnerLocked()方法代码很长,检查的代码太多了,其实主要做了如下工作:
如果要启动的activity所在的进程已经启动,那么调用应用的scheduleResumeActivity恢复activity即可(如果此activity已经存在,那么需要先scheduleNewIntent,也就是调用onNewIntent方法)
如果要启动的activity所在的app进程还没启动,那么调用mStackSupervisor.startSpecificActivityLocked启动app进程,第一次启动app时,符合这个逻辑.
ActivityStackSupervisor.startSpecificActivityLocked()方法
12345678910111213141516
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.task.stack.setLaunchTime(r); // 第一次启动app时,肯定app进程还没启动 if (app != null && app.thread != null) { ......... } // 调用AMS的startProcessLocked创建成 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }
ActivityManagerService.startProcessLocked()方法
123456789
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 */); }
实际上调用另一个同名不同参的startProcessLocked方法,介绍一下参数的含义.
processNam,即将要创建的在这个app进程的名字.传入的要启动的activity:ActivityRecord的processName.在创建ActivityRecord时,其构造方法中惠根据传入的要启动额activity的信息ActivityInfo记录的从清单xml文件中获得的进程名字,没有显示指定的话,默认为app的包名;
info要启动的app的ApplicationInfo,也是通过要启动的activity的ActivityInfo中获取的;
knownToBeDead传入的true;
intentFlags传入的0;
hostingType 传入的”activity”;
hostingName 传入的启动这个activity的intent设置的组件名,其实就是:app包名+app主actyivity的类名;
allowWhileBooting 传入的fasle;
isolated传入的false,说明要去检查当前进程列表中是否存在一个同名的进程,有的话复用这个进程.
keepIfLarge传入的false;
接下来的参数是
1234
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)
多出来的:
isolatedUid 传入的 0;
abiOverride,entryPoint,entryPointArgs,crashHandler传入的均为null;
分析其代码:
123456789101112131415161718192021222324252627282930
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; // 传入的fale.那么要检查当前系统中是否存在同名进程,存在的话并不需要重新创建了,复用即可 // 但要清除这个已经存在的进程的一些信息,比如crash的次数等. if (!isolated) { app = getProcessRecordLocked(processName, info.uid, keepIfLarge); .... }else{ app = null } ........ // 这里只考虑 app为null,也就是app进程没有被创建过 if (app == null) { checkTime(startTime, "startProcess: creating new process record"); app = newProcessRecordLocked(info, processName, isolated, isolatedUid); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); return null; } app.crashHandler = crashHandler; checkTime(startTime, "startProcess: done creating new process record"); } startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs); return (app.pid != 0) ? app : null;
newProcessRecordLocked代码就是创建一个ProcessRecord对象.
1234567891011121314151617181920
final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid) { String proc = customProcess != null ? customProcess : info.processName; BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); final int userId = UserHandle.getUserId(info.uid); int uid = info.uid; if (isolated) { ......... } final ProcessRecord r = new ProcessRecord(stats, info, proc, uid); if (!mBooted && !mBooting && userId == UserHandle.USER_OWNER && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { // 如果xml中设置了persistent为true,那么这么这里也设置为true r.persistent = true; } // 将即将要新创建的进程名字加入到AMS的mProcessNames中 addProcessNameLocked(r); return r; }
ProcessRecord是一个进程在AMS中的代表,也是AMS管理一个进程的数据结构,所以很有必要掌握其关键数据成员.
其构造方法:
12345678910111213141516
ProcessRecord(BatteryStatsImpl _batteryStats, ApplicationInfo _info, String _processName, int _uid) { mBatteryStats = _batteryStats; info = _info; isolated = _info.uid != _uid;//传入的两者相等,所以为fasle uid = _uid; userId = UserHandle.getUserId(_uid); processName = _processName; pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.versionCode)); maxAdj = ProcessList.UNKNOWN_ADJ; curRawAdj = setRawAdj = -100; curAdj = setAdj = -100; persistent = false; removed = false; lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();}
ProcessRecord
源码路径:
1
Android-6/frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
一个APK文件运行时会对应一个进程,当然,多个APK文件也可以运行在同一个进程中。ProcessRecord正是AMS记录一个进程中相关信息的类,该类中内部变量可分为三个部分:
进程文件信息
也就是与该进程对应的APK文件的内部信息.比如:
123456
ApplicationInfo info;String processName;//保存该进程中的所有APK文件包名final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
其中ApplicationInfo类定义节选如下:
1234567891011121314151617181920212223242526272829303132
public class ApplicationInfo extends PackageItemInfo implements Parcelable { public String taskAffinity;// 任务栈名称 public String permission; public String processName; public String className; ........... public String sourceDir;.................. public String[] resourceDirs;..................... public String[] sharedLibraryFiles; public String dataDir; public String nativeLibraryDir; ..................... public String primaryCpuAbi; public String secondaryCpuAbi; public int uid; ............. public int targetSdkVersion; public int versionCode;
进程的内存状态信息
这些信息将用于Linux系统的Out Of Memory(OOM)情况的处理,当发生系统内部不够用时,Linux系统会根据进程的内存状态信息,杀掉优先级比较低的进程。
12345678
int maxAdj;int curAdj;...// 是否是被AMS主动杀掉的,而不是因为内存不足而被杀掉boolean killedByAm; // True when proc has been killed by activity manager, not for RAM// 是否被杀掉boolean killed; // True once we know the process has been killed....
变量中adj的含义是adjustment,即“调整值”
进程中包含的Activity,Provider,Service等
1234567891011121314
// all activities running in the processfinal ArrayList<ActivityRecord> activities = new ArrayList<>();// all ServiceRecord running in this processfinal ArraySet<ServiceRecord> services = new ArraySet<>();// services that are currently executing code (need to remain foreground).final ArraySet<ServiceRecord> executingServices = new ArraySet<>();// All ConnectionRecord this process holdsfinal ArraySet<ConnectionRecord> connections = new ArraySet<>();// all IIntentReceivers that are registered from this process.final ArraySet<ReceiverList> receivers = new ArraySet<>();// class (String) -> ContentProviderRecordfinal ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<>();// All ContentProviderRecord process is usingfinal ArrayList<ContentProviderConnection> conProviders = new ArrayList<>();
接着分析startProcessLocked
1234567
private final void startProcessLocked( ProcessRecord app, //前面创建的ProcessRecord对象 String hostingType,// "activity" String hostingNameStr, // "app包名+主activity类名" String abiOverride,// null String entryPoint,// null String[] entryPointArgs)// null
这个方法很重要,代码也比较短,直接分析:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
// 刚启动app时,pid为0,所以不满足条件if (app.pid > 0 && app.pid != MY_PID) { }....// mProcessesOnHold记录的是系统为准备好时,就想运行的app,这里因为已经准备好了,所以从这里移除它mProcessesOnHold.remove(app);//更新cpu状态updateCpuStats();try{ ... int uid = app.uid; int[] gids = null; // 该进程使用的外部存储 int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; // 通过前面传入ProcessRecord构造方法参数可知,其为false,所以执行 if (!app.isolated) { int[] permGids = null; try{ // 得到pms final IPackageManager pm = AppGlobals.getPackageManager(); // 获取app拥有的权限组 permGids = pm.getPackageGids(app.info.packageName, app.userId); MountServiceInternal mountServiceInternal = LocalServices.getService( MountServiceInternal.class); mountExternal = mountServiceInternal.getExternalStorageMountMode(uid, app.info.packageName); }catch{ } /* * Add shared application and profile GIDs so applications can share some * resources like shared libraries and access user-wide resources */ 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)); // 从ActivityInfo中提取给进程设置的相关标志,zygote创建新城时需要用到 int debugFlags = 0; if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; // Also turn on CheckJNI for debuggable apps. It's quite // awkward to turn on otherwise. debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } // Run the app in safe mode if its manifest requests so or the // system is booted in safe mode. if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || mSafeMode == true) { debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; } if ("1".equals(SystemProperties.get("debug.checkjni"))) { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } String jitDebugProperty = SystemProperties.get("debug.usejit"); if ("true".equals(jitDebugProperty)) { debugFlags |= Zygote.DEBUG_ENABLE_JIT; } else if (!"false".equals(jitDebugProperty)) { // If we didn't force disable by setting false, defer to the dalvik vm options. if ("true".equals(SystemProperties.get("dalvik.vm.usejit"))) { debugFlags |= Zygote.DEBUG_ENABLE_JIT; } } String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info"); if ("true".equals(genDebugInfoProperty)) { debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; } if ("1".equals(SystemProperties.get("debug.jni.logging"))) { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } if ("1".equals(SystemProperties.get("debug.assert"))) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } // 提取进行运行时的abi,如:armeabi,armeabi-v7a等 // 对于有so库的app来说,PMS会解析除这个变量 String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi; // 对于没有so库的app来说,设置为系统的主abi if (requiredAbi == null) { requiredAbi = Build.SUPPORTED_ABIS[0]; } // 设置进程指令集,如arm,arm64,x86,mips等 String instructionSet = null; if (app.info.primaryCpuAbi != null) { instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi); } // 墙面获取到的信息,填充到ProcessRecord中, app.gids = gids; app.requiredAbi = requiredAbi; app.instructionSet = instructionSet; // 设置进程的入口点,也就是执行代码的入口点 // 传入的为null,所以为true boolean isActivityProcess = (entryPoint == null); // 设置进程入口点 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);// 创建app进程的时候为falseif (app.isolated) { mBatteryStatsService.addIsolatedUid(app.uid, app.info.uid); } // 电源管理mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);// 如果设置该变量为true,表明该进程要一直存在,当被杀死时,要被重新唤醒.所以加入watchdog中if (app.persistent) {watchdog.getInstance().processStarted(app.processName, startResult.pid); }......// 继续初始化ProcessRecord,app.setPid(startResult.pid);//前面创建进程时,返回了进程号pidapp.usingWrapper = startResult.usingWrapper;app.removed = false;app.killed = false;app.killedByAm = false;synchronized (mPidsSelfLocked) {// 将App进程的ProcessRecord以其进程号为索引加入到AMS的mPidsSelfLocked中// 后续ActivityThread.main中调用AMS的attachApplicationLocked()方法会以进程号,重新拿到其ProcessRecordthis.mPidsSelfLocked.put(startResult.pid, app);// 前面设置了该变量为trueif (isActivityProcess) {// 向AMS发送PROC_START_TIMEOUT_MSG消息 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, startResult.usingWrapper ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);}}
startProcessLocked()方法的流程是:准备好启动进程的相关参数,例如进程权等,调用Process的start()方法来启动进程.启动进程后,利用返回的信息初始化ProcessRecord,比如拿到进程pid等.另外当进程需要常驻内存时,需要将其添加到watchdog中.
启动进程之后,AMS给自己发送一个PROC_START_TIMEOUT_MSG消息,这个消息用来防止进程启动时间超时.如果start()方法返回结果中usingWrapper为true,超时时间设置为1200秒,否则设置为10秒.如果时间到了进程还没启动AMS将弹出ANR对话框.
App进程启动后,会先执行ActivityThread.main()方法,该方法会调用AMS的attachApplicationLocked()方法,这个方法中会将这个PROC_START_TIMEOUT_MSG消息,从消息队列中移除.如果在规定的超时时间内没移除该消息,就会导致进程启动超时机制被触发.
Process.start()方法
源码位置:
1
Android-6/frameworks/base/core/java/android/os/Process.java
123456789101112131415161718192021222324
public static final ProcessStartResult start( final String processClass,//进程的入口点,android.app.ActivityThread final String niceName,//进程的名字 int uid, int gid, int[] gids,// 进程uid gid,权限相关 int debugFlags, // app在清单文件中设置的进程相关标记 ,以及系统设置的进程标记,例如是否让VM执行checkjni等 int mountExternal,// 外部存储相关 int targetSdkVersion,// app中指定的targetSdkVersion String seInfo,//SElinux相关,设置进程安全上下文使用 String abi,//进程abi,如armeabi,armeabi-v7a等 String instructionSet,// 指令集.如arm,arm64,x86,mips等 String appDataDir,//app数据沙箱目录 String[] zygoteArgs //传入的为null ) { try { return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); throw new RuntimeException( "Starting VM process through Zygote failed", ex); }}
在Process类的startViaZygote方法里,会计算启动应用进程用的各个参数,然后再调用zygoteSendArgsAndGetResult方法将这些参数通过socket发送给zygote进程,zygote进程会孵化出新的dalvik应用进程,然后告诉ActivityManagerService新启动的进程的pid。
Process.startViaZygote()方法
12345678910111213141516171819202122232425262728293031323334353637
private static ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { ArrayList<String> argsForZygote = new ArrayList<String>(); // 开始整理传入的参数 argsForZygote.add("--runtime-args"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) { argsForZygote.add("--enable-jni-logging"); } .......... if (appDataDir != null) { argsForZygote.add("--app-data-dir=" + appDataDir); } ..... argsForZygote.add(processClass); // 传入的为null if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } } // 将这些参数通过socket发送给zygote进程,用来创建进程 return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); }
其中openZygoteSocketIfNeeded()方法用来连接Zygote socket.从Android 5.0开始,Android开始支持64位系统.对于64位Android系统来说,存在两个zygote进程:
主zygote,对应的socket:/dev/socket/zygote
次zygote,对应的scoket:/dev/socket/zygote_secondary
至于主次zygote哪个对应于64位的zygote,哪个是32位的zygote.则有init进程解析相关rc文件决定.
连接zygote时,首先连接主zygote.主次zygote一个是64,一个是32,所以支持的abi肯定不同.根据当前的abi来选择与zygote32还是zygote64来进行通信。
openZygoteSocketIfNeeded()方法返回值是ZygoteState对象
123456
public static class ZygoteState { final LocalSocket socket; final DataInputStream inputStream; final BufferedWriter writer; final List<String> abiList; .......
Process.zygoteSendArgsAndGetResult()方法
123456789101112131415161718192021222324252627282930313233343536373839404142
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())); // 开始新的一行(相当于发了"\n") 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); // 开始新的一行(相当于发了"\n") writer.newLine(); } // 将信息发送给zygote writer.flush(); ProcessStartResult result = new ProcessStartResult(); // 通过socket读取zygote的返回信息(阻塞到有数为止) // zygote先发送创建的进程的pid,为-1表示创建失败 result.pid = inputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } // 然后发送的是一个boolean值,于超时间的设定有关 result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); } }
Zygote孵化App进程
zygote进程将ZygoteInit作为启动类,会执行它的main方法,先注册Zygote Socket,然后调用runSelectLoop方法,runSelectLoop方法会调用方法在Zygote Socket上监听请求,如果别的进程通过Zygote Socket请求孵化进程,则孵化进程。
ZygoteInit.main:
1234567891011
public static void main(String argv[]) { try { runSelectLoop(abiList); .... } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { closeServerSocket(); throw ex; }}
runSelectLoop()方法会抛出异常MethodAndArgsCaller,从而进入caller.run(),也就是MethodAndArgsCaller.run()方法。
ZygoteInit.runSelectLoop()
这个方法是zygote用来监听和处理创建应用进程的请求.注意此方法是一个死循环!!!通过ZygoteConnection.runOnce()抛出MethodAndArgsCaller异常返回ZygoteInit.main中.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); // 将 zygote socket 的 fd加入数组 fds.add(sServerSocket.getFileDescriptor()); peers.add(null); // 这里使用到了linux的poll机制 while (true) { StructPollfd[] pollFds = new StructPollfd[fds.size()]; for (int i = 0; i < pollFds.length; ++i) { pollFds[i] = new StructPollfd(); pollFds[i].fd = fds.get(i); pollFds[i].events = (short) POLLIN; } try { Os.poll(pollFds, -1); } catch (ErrnoException ex) { throw new RuntimeException("poll failed", ex); } for (int i = pollFds.length - 1; i >= 0; --i) { //采用I/O多路复用机制,当客户端发出连接请求或者数据处理请求时,跳过continue,执行后面的代码 if ((pollFds[i].revents & POLLIN) == 0) { continue; } if (i == 0) { //表示zygote socket中有连接到来,那么就要创建客户端连接 // 实际上就是执行socket accept操作 // 然后把创建的这个连接也加入到监听数组中,索引肯定大于0了 // 那么一旦这个连接中有数据来了,i肯定大于0 ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { //调用ZygoteConnection.runOnce()处理客户端数据事务 boolean done = peers.get(i).runOnce(); // 处理完之后,断开连接,并且不在监听这个连接 if (done) { peers.remove(i); fds.remove(i); } } } }}
ZygoteConnection.runOnce()
这个方法首先肯定是先从 socket接受传递过来的启动进程的线骨干参数.然后解析参数.检查权限,创建进程,然后处理父子进程:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { String args[]; Arguments parsedArgs = null; FileDescriptor[] descriptors; try { //接受参数 args = readArgumentList(); descriptors = mSocket.getAncillaryFileDescriptors(); } catch (IOException ex) { ........................ } ....... try { // 解析参数 parsedArgs = new Arguments(args); ....... // 权限检查 applyUidSecurityPolicy(parsedArgs, peer); applyInvokeWithSecurityPolicy(parsedArgs, peer); applyDebuggerSystemProperty(parsedArgs); applyInvokeWithSystemProperty(parsedArgs); ..... pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir); }catch{ ...... } try { if (pid == 0) { // in child // 创建的app进程 IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); // should never get here, the child is expected to either // throw ZygoteInit.MethodAndArgsCaller or exec(). return true; } else { // in parent...pid of < 0 means failure // zygote进程 IoUtils.closeQuietly(childPipeFd); childPipeFd = null; return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); }}
Zygote.forkAndSpecialize()方法
1234567891011121314151617
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, String instructionSet, String appDataDir) { VM_HOOKS.preFork(); int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, instructionSet, appDataDir); // Enable tracing as soon as possible for the child process. if (pid == 0) { Trace.setTracingEnabled(true); // Note that this event ends at the end of handleChildProc, Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); } VM_HOOKS.postForkCommon(); return pid;}
从代码中可知zygote孵化进程还是依靠的jni native方法完成的.
在真正孵化进程之前,要做一些前期工作,比如暂停zygote中运行的线程,从而提高fork效率.这些是由VM_HOOKS.preFork()完成的.
1234567891011
public void preFork() { Daemons.stop();//停止4个Daemon子线程 waitUntilAllThreadsStopped();//等待所有子线程结束 token = nativePreFork();//完成gc堆的初始化工作}public static void stop() { HeapTaskDaemon.INSTANCE.stop(); //Java堆整理线程 ReferenceQueueDaemon.INSTANCE.stop(); //引用队列线程 FinalizerDaemon.INSTANCE.stop(); //析构线程 FinalizerWatchdogDaemon.INSTANCE.stop(); //析构监控线程}
守护线程Stop方式是先调用目标线程interrrupt()方法,然后再调用目标线程join()方法,等待线程执行完成.
Zygote.nativeForkAndSpecialize()方法
源码路径:
1
Android-6/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
123456789101112131415
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint debug_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring se_name, jintArray fdsToClose, jstring instructionSet, jstring appDataDir) { // Grant CAP_WAKE_ALARM to the Bluetooth process. jlong capabilities = 0; if (uid == AID_BLUETOOTH) { capabilities |= (1LL << CAP_WAKE_ALARM); } return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, fdsToClose, instructionSet, appDataDir);}
实际上调用下面的方法创建进程:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint debug_flags, jobjectArray javaRlimits, jlong permittedCapabilities, jlong effectiveCapabilities, jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jstring instructionSet, jstring dataDir) { //设置子进程的signal信号处理函数 SetSigChldHandler(); // fork进程 // 父进程中,fork返回新创建的子进程的pid; // 子进程中,fork返回0 // 执行完这句代码,后面的代码父子进程都会执行,所以要根据返回值做不同处理. pid_t pid = fork(); if (pid == 0) { // app进程 gMallocLeakZygoteChild = 1; DetachDescriptors(env, fdsToClose); // Keep capabilities across UID change, unless we're staying root. // 使用linux capabilities 权限机制,root进程不使用 if (uid != 0) { EnableKeepCapabilities(env); } // 由于前面开始了capabilities机制,所以可以放弃某些app进程不该拥有的能力了 DropCapabilitiesBoundingSet(env); // x86架构运行arm文件时,需要一个bridge bool use_native_bridge = !is_system_server && (instructionSet != NULL) && android::NativeBridgeAvailable(); if (use_native_bridge) { ScopedUtfChars isa_string(env, instructionSet); use_native_bridge = android::NeedsNativeBridge(isa_string.c_str()); } if (use_native_bridge && dataDir == NULL) { use_native_bridge = false; ALOGW("Native bridge will not be used because dataDir == NULL."); } // 进程外置外部存储 // 6.0中,因为允许动态授权权限,比如说app申请了对外部存储的读写权限,可能用户之后会关闭写权限等 // 所以6.0中,改变了对外部存储的管理策略,这个以后单独讲 // 这里只需要直到根据mount_external // 有三个挂在点:/mnt/runtime/default,storageSource = "/mnt/runtime/read",storageSource = "/mnt/runtime/write" // 6.0之前,都是直接指向外部存储的 if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) { ALOGW("Failed to mount emulated storage: %s", strerror(errno)); if (errno == ENOTCONN || errno == EROFS) { } else { ALOGE("Cannot continue without emulated storage"); RuntimeAbort(env); } } if (!is_system_server) { //对于非system_server子进程,则创建进程组 // 创建文件夹/acct/uid_<uid>/,权限0750,system:system // 创建文件夹/acct/uid_<uid>/pid_<pid>,权限0750,system:system // open文件/acct/uid_<uid>/pid_<pid>/cgroup.procs,记录进程号 int rc = createProcessGroup(uid, getpid()); if (rc != 0) { ....................... } } //设置设置group SetGids(env, javaGids); //设置资源limit SetRLimits(env, javaRlimits); if (use_native_bridge) { ScopedUtfChars isa_string(env, instructionSet); ScopedUtfChars data_dir(env, dataDir); android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str()); } int rc = setresgid(gid, gid, gid); if (rc == -1) { ALOGE("setresgid(%d) failed: %s", gid, strerror(errno)); RuntimeAbort(env); } rc = setresuid(uid, uid, uid); if (rc == -1) { ALOGE("setresuid(%d) failed: %s", uid, strerror(errno)); RuntimeAbort(env); } if (NeedsNoRandomizeWorkaround()) { // Work around ARM kernel ASLR lossage (http://b/5817320). int old_personality = personality(0xffffffff); int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE); if (new_personality == -1) { ALOGW("personality(%d) failed: %s", new_personality, strerror(errno)); } } // 设置能力,除了蓝颜进程外,其他app进程,permittedCapabilities为0 SetCapabilities(env, permittedCapabilities, effectiveCapabilities); //设置调度策略 SetSchedulerPolicy(env); const char* se_info_c_str = NULL; // PMS在app安装的时候,就会记录seinfo.第三方app一般都为default. ScopedUtfChars* se_info = NULL; if (java_se_info != NULL) { se_info = new ScopedUtfChars(env, java_se_info); se_info_c_str = se_info->c_str(); if (se_info_c_str == NULL) { ALOGE("se_info_c_str == NULL"); RuntimeAbort(env); } } const char* se_name_c_str = NULL; ScopedUtfChars* se_name = NULL; if (java_se_name != NULL) { se_name = new ScopedUtfChars(env, java_se_name); se_name_c_str = se_name->c_str(); if (se_name_c_str == NULL) { ALOGE("se_name_c_str == NULL"); RuntimeAbort(env); } } //设置selinux上下文 rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str); if (rc == -1) { ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid, is_system_server, se_info_c_str, se_name_c_str); RuntimeAbort(env); } // Make it easier to debug audit logs by setting the main thread's name to the // nice name rather than "app_process". if (se_info_c_str == NULL && is_system_server) { se_name_c_str = "system_server"; } // 第三方app为default if (se_info_c_str != NULL) { SetThreadName(se_name_c_str); } delete se_info; delete se_name; //在Zygote子进程中,设置信号SIGCHLD的处理器恢复为默认行为 UnsetSigChldHandler(); //调用zygote.callPostForkChildHooks() env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags, is_system_server ? NULL : instructionSet); if (env->ExceptionCheck()) { ALOGE("Error calling post fork hooks."); RuntimeAbort(env); } } else if (pid > 0) { // the parent process } return pid;}
12345678
private static void callPostForkChildHooks(int debugFlags, String instructionSet) { VM_HOOKS.postForkChild(debugFlags, instructionSet); } public void postForkChild(int debugFlags, String instructionSet) { nativePostForkChild(token, debugFlags, instructionSet); Math.setRandomSeedInternal(System.currentTimeMillis());}
12345678910111213141516171819
static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags, jstring instruction_set) { Thread* thread = reinterpret_cast<Thread*>(token); //设置新进程的主线程id thread->InitAfterFork(); .. if (instruction_set != nullptr) { ScopedUtfChars isa_string(env, instruction_set); InstructionSet isa = GetInstructionSetFromString(isa_string.c_str()); Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload; if (isa != kNone && isa != kRuntimeISA) { action = Runtime::NativeBridgeAction::kInitialize; } //【见流程6-2-2-1-1-1】 Runtime::Current()->DidForkFromZygote(env, action, isa_string.c_str()); } else { Runtime::Current()->DidForkFromZygote(env, Runtime::NativeBridgeAction::kUnload, nullptr); }}
1234567891011121314151617181920212223242526
void Runtime::DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const char* isa) { is_zygote_ = false; if (is_native_bridge_loaded_) { switch (action) { case NativeBridgeAction::kUnload: UnloadNativeBridge(); //卸载用于跨平台的桥连库 is_native_bridge_loaded_ = false; break; case NativeBridgeAction::kInitialize: InitializeNativeBridge(env, isa);//初始化用于跨平台的桥连库 break; } } //创建Java堆处理的线程池 heap_->CreateThreadPool(); //重置gc性能数据,以保证进程在创建之前的GCs不会计算到当前app上。 heap_->ResetGcPerformanceInfo(); if (jit_.get() == nullptr && jit_options_->UseJIT()) { //当flag被设置,并且还没有创建JIT时,则创建JIT CreateJit(); } //设置信号处理函数 StartSignalCatcher(); //启动JDWP线程,当命令debuger的flags指定"suspend=y"时,则暂停runtime Dbg::StartJdwp();}
继续看Zygote.forkAndSpecialize()
会调用:
1
VM_HOOKS.postForkCommon();
123456789
public void postForkCommon() { Daemons.start();}public static void start() { ReferenceQueueDaemon.INSTANCE.start(); FinalizerDaemon.INSTANCE.start(); FinalizerWatchdogDaemon.INSTANCE.start(); HeapTaskDaemon.INSTANCE.start();}
VM_HOOKS.postForkCommon的主要功能是在fork新进程后,启动Zygote的4个Daemon线程,java堆整理,引用队列,以及析构线程(前面暂停了)。
ZygoteConnection.handleChildProc()–子进程初始化
1234567891011121314151617181920212223242526272829303132333435
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { //关闭Zygote的socket两端的连接 closeSocket(); ZygoteInit.closeServerSocket(); // 关闭从zygote继承的文件描述 if (descriptors != null) { try { Os.dup2(descriptors[0], STDIN_FILENO); Os.dup2(descriptors[1], STDOUT_FILENO); Os.dup2(descriptors[2], STDERR_FILENO); for (FileDescriptor fd: descriptors) { IoUtils.closeQuietly(fd); } newStderr = System.err; } catch (ErrnoException ex) { Log.e(TAG, "Error reopening stdio", ex); } } if (parsedArgs.niceName != null) { //设置进程名 Process.setArgV0(parsedArgs.niceName); } if (parsedArgs.invokeWith != null) { ........................... } else { //执行ActivityThread.main RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null); }}
RuntimeInit.ZygoteInit()方法
1234567891011121314
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit"); //重定向log输出 redirectLogStreams(); //一些初始化 commonInit(); // zygote初始化 nativeZygoteInit(); // 应用初始化 applicationInit(targetSdkVersion, argv, classLoader);}
RuntimeInit.commonInit()方法
commonInit()方法主要进行一些简单初始化:设置异常处理,设置时区,重置Android log 系统,设置http.agent属性
12345678910111213141516171819202122232425
private static final void commonInit() { // 设置默认的未捕捉异常处理方法 // app也可以调用这个方法设置自己的处理方法,例如在处理方法中把产生的异常信息发送到公司服务器中 Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler()); // 设置市区,中国时区为"Asia/Shanghai" TimezoneGetter.setInstance(new TimezoneGetter() { @Override public String getId() { return SystemProperties.get("persist.sys.timezone"); } }); TimeZone.setDefault(null); //重置log配置 LogManager.getLogManager().reset(); new AndroidConfig(); // 设置默认的HTTP User-agent格式,用于 HttpURLConnection。 String userAgent = getDefaultUserAgent(); System.setProperty("http.agent", userAgent); // 设置socket的tag,用于网络流量统计 NetworkManagementSocketTagger.install();}
RuntimeInit.nativeZygoteInit()方法
源码路径:
1
Android-6/frameworks/base/core/jni/AndroidRuntime.cppAndroid-6/frameworks/base/cmds/app_process/App_main.cpp
123456789
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz){ gCurRuntime->onZygoteInit(); //此处的gCurRuntime为AppRuntime,是在AndroidRuntime.cpp中定义的}virtual void onZygoteInit(){ sp<ProcessState> proc = ProcessState::self(); proc->startThreadPool(); //启动新binder线程}
ProcessState::self()是单例模式,主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver().
该方法主要进行binder的初始化,这样app就可以使用binder了.
RuntimeInit.applicationInit()方法
开始指向ActivityThread.main().
1234567891011121314151617181920
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { //true代表应用程序退出时不调用AppRuntime.onExit(),否则会在退出前调用 nativeSetExitWithoutCleanup(true); //设置虚拟机的内存利用率参数值为0.75 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()); // let the process exit return; } // Remaining arguments are passed to the start class's static main invokeStaticMain(args.startClass, args.startArgs, classLoader); }
RuntimeInit.invokeStaticMain()方法
1234567891011121314151617181920212223242526272829303132
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { Class<?> cl; try { // 传入的classLoader为null cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { throw new RuntimeException( "Missing class when invoking static main " + className, ex); } // 找到main方法 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); } // main方法必须是static public类型的 int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException( "Main method is not public and static on " + className); } //通过抛出异常,回到ZygoteInit.main()。这样做好处是能清空栈帧,提高栈帧利用率。 // m就是找到的main方法 throw new ZygoteInit.MethodAndArgsCaller(m, argv);}
MethodAndArgsCaller.run()方法
12345678910111213141516
public void run() { try { // mMethod就是ActivityThread.main方法 mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { Throwable cause = ex.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } throw new RuntimeException(ex); } }
到此位置app的进程算是创建完毕了,进程执行的第一个方法也找到是谁了.
- Android6.0之AMS启动app中篇之创建app进程
- Android6.0之AMS如何启动app中篇之Task的管理
- Android6.0之AMS启动App下篇
- Android6.0之AMS如何启动app上篇
- Android6.0之AMS启动
- Android6.0之AMS前奏
- Android6.0之AMS数据结构梳理
- Android6.0之AMS管理Service前奏
- Android6.0 AMS 新进程中启动Activity
- AMS APP进程间通信
- Android6.0 AMS启动Activity(二) 启动进程然后启动Activity
- Android6.0 AMS启动Activity(二) 启动进程然后启动Activity
- android6.0源码分析之AMS服务源码分析
- android6.0源码分析之AMS服务源码分析
- Android6.0 AMS启动Activity(四) AMS内部成员变量
- Android6.0 AMS启动Activity(三) 进程内部启动Activity
- Android6.0 AMS启动Activity(五) 在新进程中启动Activity
- Android6.0 AMS启动Activity(三) 进程内部启动Activity
- React系列之--组件的生命周期
- 装饰器模式
- 注解(Annotation)自定义注解(一)
- ajax防止重复提交
- Oracle-获取本周、本月、本季、本年的第一天和最后一天
- Android6.0之AMS启动app中篇之创建app进程
- NDK-JNI实战教程(二) JNI官方中文资料
- 最短路径
- webx学习总结之页面流程执行过程详细分析(转载)
- Android中ExpandableListView的使用
- [BZOJ 2096][Poi2010]Pilots:单调队列
- 高性能开源持久化消息队列
- [Modern Compiler] Activation Records: Stack Frames
- QT5 仿最新QQ设置面板