android N进程启动流程(二)(上一个activity的暂停、进程启动、绑定进程与创建application)

来源:互联网 发布:蜂群算法 多目标规划 编辑:程序博客网 时间:2024/06/07 19:03

android N进程启动流程(二)(上一个activity的暂停、进程启动、绑定进程与创建application)

第二部分将分为:上一个activity的暂停、进程启动、绑定进程与创建application

5. 上一个activity的暂停

上一个activity的暂停
图5.1 上一个activity的暂停

接着章节3.6的startActivityUnchecked中会调用最后有调用resumeFocusedStackTopActivityLocked,我们接下去从这里开始讲解。

5.1 resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java)

resumeFocusedStackTopActivityLocked恢复当前focus的堆栈stack中的顶端活动对象top activity

1) 上面章节3.6中setTaskFromReuseOrCreateNewTask->computeStackFocus->mSupervisor.getStack已经创建了mTargetStack,并将其添加到ActivityDisplay的mStack中去。
2) 章节3.6中moveToFront的insertTaskAtTop中也设置了需要启动的应用如test2.com.myapplication成为堆栈顶端Top的进程
3) 章节4.2中setFocusStackUnchecked也设置了mTargetStack为test2

    //上面章节3.6中setTaskFromReuseOrCreateNewTask已经创建了mTargetStack,    //章节3.6中moveToFront的insertTaskAtTop中也设置了需要启动的应用如test2.com.myapplication    //成为堆栈顶端Top的进程    boolean resumeFocusedStackTopActivityLocked(            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {        if (targetStack != null && isFocusedStack(targetStack)) {            //targetStack不为null,而且isFocusedStack也是test2,故此处是会进来的            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);        }        //...    }

5.2 resumeTopActivityUncheckedLocked(ActivityStack.java)

resumeFocusedStackTopActivityLocked恢复当前focus堆栈stack中的顶端活动对象
1) 此处的stack this对象是test2上一章节5.1中说的mTargetStack
2) 此时是第一次看到resumeTopActivityInnerLocked,故是第一次进入,传递的prev是test2.com.myapplication我们先看第一次进入该函数的处理逻辑(第二次的请忽略先)
3) 此处逻辑依次是resumeTopActivityUncheckedLocked->resumeTopActivityInnerLocked->pauseBackStacks
4) 第一次进入由于在pauseBackStacks返回有需要pause的应用,故pausing==true,pauseBackStacks做完不久就直接返回了

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {        //....        result = resumeTopActivityInnerLocked(prev, options);        //....    }    //第一次进来的时候prev是test2.com.myapplication(所以会先pause上一个应用如com.android.launcher);    //第二次进来是prev是com.android.launcher,此时launcher已经pause了,    //会进入下一个应用的resume流程(如test2.com.myapplication)    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {        //...        //第一次进来topRunningActivityLocked是test2,第二次进来也是test2,        //此处是在moveActivityStackToFront中已经设置过了        final ActivityRecord next = topRunningActivityLocked();        //...        //此处allPausedActivitiesComplete是true,不会进入这里,        //说明之前已经没有需要pause的应用(第一次进来mPausingActivity还没有设置过==null)        //或者pause完成(第二次进来)        if (!mStackSupervisor.allPausedActivitiesComplete()) {            …            return false;        }        //...        //是否有设置标志位在pausing的时候resume,默认没有设置都是false        final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;        //此处判断是否有需要pasue的进程(是所有stack而不仅仅是当前stack),        //第一次进来会pause launcher(launcher的堆栈中有mResumedActivity,        //但是章节4.2已经将焦点切换到test2)故反馈pausing==true,第二次直接返回pausing==false        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);        //mResumedActivity一直都是null(由于当前mTargetStack是新new出来的给进程test2使用),        //只有在test2 resume之后才会设置,如在minimalResumeActivityLocked之后设置,故不会走下面的逻辑        if (mResumedActivity != null) {            //...        }        //第一次走的pausing是true(代表有需要暂停的应用,如launcher),第二次pausing是false        if (pausing) {            //...            //第一次进来到这里就结束了            return true;        //此处一般都是不走的mResumedActivity == null,第二次pausing是false,        //但是还是有activity继续resume(allResumedActivitiesComplete返回false)        } else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&                mStackSupervisor.allResumedActivitiesComplete()) {            ...            return true;        }        //第二次时会进来这里prev != next,此处next代表test2.com.myapplication,        //prev代表com.android.launcher        if (prev != null && prev != next) {            if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev)                    && next != null && !next.nowVisible) {                //等待prev的界面launcher隐藏,此处在mStackSupervisor的                //processStoppingActivitiesLocked时才会remove                mStackSupervisor.mWaitingVisibleActivities.add(prev);            } else {            //...        }        //...        //第二次进来时prev == com.android.launcher        if (prev != null) {            //launcher是没有finishing的,不进入这里            if (prev.finishing) {                //...            //准备resume test2.com.myapplication时prev代表com.android.launcher,会进来这里            } else {                //prev.task不等于next.task,mLaunchTaskBehind是false,                //WMS中传输类型是TRANSIT_TASK_OPEN                mWindowManager.prepareAppTransition(prev.task == next.task                        ? TRANSIT_ACTIVITY_OPEN                        : next.mLaunchTaskBehind                                ? TRANSIT_TASK_OPEN_BEHIND                                : TRANSIT_TASK_OPEN, false);            }        } else {            //...        }        //...        //此处next(test2.com.myapplication)进程都还没有起来,不会进入这里        if (next.app != null && next.app.thread != null) {            //...        //next(test2.com.myapplication)进入的是else        } else {            //第一次启动hasBeenLaunched肯定是false,所以会进入此处            if (!next.hasBeenLaunched) {                next.hasBeenLaunched = true;            } else {                ...            }            //这里才是真正启动test2进程的地方            mStackSupervisor.startSpecificActivityLocked(next, true, true);        }        //...    }

5.3 pauseBackStacks(ActivityStackSupervisor.java)

pauseBackStacks遍历ActivityDisplay显示设备中的所有栈,当循环到luancher的时候,由于launcher已经不是focus的stack栈,但是它的mResumedActivity仍然存在,代表这个activity需要进行pause暂停的操作。

    boolean pauseBackStacks(boolean userLeaving, boolean resuming, boolean dontWait) {        //...        //遍历stacks当前显示设备的所有堆栈        final ActivityStack stack = stacks.get(stackNdx);        //stack是launcher,isFocusedStack是false,mResumedActivity是launcher不等于null        if (!isFocusedStack(stack) && stack.mResumedActivity != null) {            //launcher的stack进行pause的操作,注意resuming是true,dontWait是false,            //userLeaving是true,在章节3.6 startActivityUnchecked->setInitialState中设置            someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,                    dontWait);        //...    }

5.4 startPausingLocked(ActivityStack.java)

1) startPausingLocked这个函数是启动应用暂停pause(如此处的是上一个应用launcher),设置当前状态为pausing
2) 进入ActivityThread处理暂停任务之前会在eventlog中输出am_pause_activity的信息,表示将要开始该应用的暂停了
3) 不过最重要的函数还是ActivityThread的schedulePauseActivity,该函数会处理pause任务

    //userLeaving==true, uiSleeping==false, resuming==true, dontWait==false    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,            boolean dontWait) {        //第一次进来mPausingActivity是null,应用没有暂停就没有所谓的mPausingActivity        if (mPausingActivity != null) {            //...        }        //mResumedActivity是当前resume的activity,此处是launcher        ActivityRecord prev = mResumedActivity;        //注意此处pause之后将设置mResumedActivity==null,代表没有该Stack没有resume的activity了        mResumedActivity = null;        //launcher设置为正在pause的进程        mPausingActivity = prev;        //设置上一个暂停的应用        mLastPausedActivity = prev;        //标定该进程在PAUSING状态        prev.state = ActivityState.PAUSING;        //此处next是test2,章节4.2的insertTaskAtTop已经设置过        final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();        //pause应用会触发cpu状态更新,可以使用adb shell dumpsys cpuinfo查询        mService.updateCpuStats();        //prev是launcher,里面的app和thread都是已经创建的,所有此处会进入        if (prev.app != null && prev.app.thread != null) {            try {                //event log中的am_pause_activity,代表应用的pause开始                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,                        prev.userId, System.identityHashCode(prev),                        prev.shortComponentName);                //cpu前后台切换,用于耗电统计                mService.updateUsageStats(prev, false);                //ActivityThread里面的方法是handle(异步),此处才是activity的真正的pause执行的地方                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,                        userLeaving, prev.configChangeFlags, dontWait);            //...        //mPausingActivity就是launcher,所以会进来此处。        if (mPausingActivity != null) {            //uiSleeping==false            if (!uiSleeping) {                //应用的pause的时候,会暂停接收输入事件,此时系统触摸了不反馈给上层                prev.pauseKeyDispatchingLocked();            }            //dontWait==false,章节5.2中设置dontWaitForPause            if (dontWait) {                //只有当dontWait是true的时候才会走这里,就是不等待pause完成                completePauseLocked(false);                return false;            } else {                //launcher的最后onpause会走到这里来                Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);                msg.obj = prev;                prev.pauseTime = SystemClock.uptimeMillis();                //设置pause的超时时间为500ms                mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);                //返回ture,代表有响应的activity正在pausing,                //故在章节5.2 resumeTopActivityInnerLocked运行完该函数后不久就返回了                return true;            }        } else {        //...    }

ps:上面也看到了pause的时候会限制输入事件,如果应用一直重启又挂掉又重启,此时如果不停调用pause/finish的话会限制输入事件的分发pauseKeyDispatchingLocked,当然这种情况只是极端情况,一般不会出现

5.5 schedulePauseActivity(ActivityThread.java)

1) schedulePauseActivity这个是通过handler(一直想吐槽这个hander也类名也太简洁了的点吧,一个”H”就搞定)在UI主线程里面做的事情
2) 主要流程是schedulePauseActivity->PAUSE_ACTIVITY->handlePauseActivity->performPauseActivity->performPauseActivityIfNeeded
3) 我们主要关注performPauseActivityIfNeeded当前activity暂停(这部分本章节讲解)、activityPaused通知AMS上一个activity暂停完成(这部分下一章里讲解)。

    //ActivityThread给外部提供的接口,pause暂停是通过应用的主线程进行处理    public final void schedulePauseActivity(IBinder token, boolean finished,            boolean userLeaving, int configChanges, boolean dontReport) {        int seq = getLifecycleSeq();        //...        //finished等于false,走的是PAUSE_ACTIVITY,userLeaving==true,dontReport==dontWait==false        sendMessage(                finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,                token,                (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),                configChanges,                seq);    }    //handler传递,调用的是handlePauseActivity    case PAUSE_ACTIVITY: {        //...        //进入pause的处理        handlePauseActivity((IBinder) args.arg1, false,                (args.argi1 & USER_LEAVING) != 0, args.argi2,                (args.argi1 & DONT_REPORT) != 0, args.argi3);        //...    } break;    //finished是false,userLeaving==true,dontReport==false    private void handlePauseActivity(IBinder token, boolean finished,            boolean userLeaving, int configChanges, boolean dontReport, int seq) {        ActivityClientRecord r = mActivities.get(token);        ...        if (r != null) {            //userLeaving一般都是true            if (userLeaving) {                //会进入此处,会调用activity.performUserLeaving,当离开用户可视的时候会调用                performUserLeavingActivity(r);            }            //...            //此处是pause上一个应用launcher,isPreHoneycomb是android3.0之前用的,此处是false            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");            //dontReport一般没有设置都是false,故一般都是进入此处的            if (!dontReport) {                try {                    //通知AMS上一个应用完成pause了,这里接下去就会resume下一个应用(先启动进程),                    //下一章会讲到                    ActivityManagerNative.getDefault().activityPaused(token);                } catch (RemoteException ex) {                    throw ex.rethrowFromSystemServer();                }            }            mSomeActivitiesChanged = true;        }    }    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,            boolean saveState, String reason) {        //saveState是false,不跑这里        if (!r.activity.mFinished && saveState) {            callCallActivityOnSaveInstanceState(r);        }        //这里才是pause activity的地方        performPauseActivityIfNeeded(r, reason);        // 将当前pause的应用的OnActivityPausedListener暂停监听去除        ArrayList<OnActivityPausedListener> listeners;        synchronized (mOnPauseListeners) {            listeners = mOnPauseListeners.remove(r.activity);        }        //...        for (int i = 0; i < size; i++) {            //此处是调用注册了该activity thread的监听onPaused的回调,            //如NfcAdapter.java中的ActivityThread.currentActivityThread()            //.registerOnActivityPausedListener(activity,mForegroundDispatchListener);            listeners.get(i).onPaused(r.activity);        }        //...    }

5.6 performPauseActivityIfNeeded(ActivityThread.java)

1) 通过代理类Instrumentation调用callActivityOnPause,其调用的是activity的performPause(分别会调用mFragments.dispatchPause、activity的onPause,application的ActivityLifecycleCallback生命周期回调方法onActivityPaused)
2) OnPause调用完成后会在event log中写入am_on_paused_called,代表activity的OnPause已经完成(如果你使用onpause有问题,可以从am_pause_activity到am_on_paused_called之间所花费的时间做初步判断)
3) 注意OnPause完成之后paused会赋值为true,代表当前是暂停状态

    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {        if (r.paused) {            //如果之前paused==true了就直接返回,activitythread创建设置成false,            //oncreate将设置成ture,onresume将设置成false            //上一个activity的上一个状态是onresume,正在pause,故此处是paused==false            return;        }        try {            //这里解释一下mCalled,这个值是用来判断是否有调用activity生命周期的函数            r.activity.mCalled = false;            //这就就是具体调用activity的performPause的地方            //(包括mFragments.dispatchPause、activity的onPause,            //application的ActivityLifecycleCallback生命周期回调方法onActivityPaused),            //运行完之后mCalled会设置成true            mInstrumentation.callActivityOnPause(r.activity);            //写event log,am_on_paused_called,说明pause已经调用            EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),                    r.activity.getComponentName().getClassName(), reason);            //...        //运行了之后设置标致位paused==true        r.paused = true;    }

到目前为止基本上把上一个activity的OnPause流程讲解完了。

6. 进程启动(一)am_proc_start

讲了一大堆,是不是发现我们需要启动的进程test2怎么还没到呢,流程有点长,目前android的默认架构就是这样,大家耐心的继续看下去,我们这一章节就开始讲到进程启动(这部分应该很多文章都有提到,了解的同学可以不必细看)。

其实这些流程只是学习作用,对我们了解android架构有一定帮助,解决问题(仅针对那些代码不规范自己改出来的问题)时有帮助,不过这些都不是关注的重点,我们关注的是如何优化整个流程,如果没有明确这个目的,对我们来说是没有很大提升的。路漫漫其修远,我们先把流程梳理清楚,一步步来…

进程启动(一)
图6.1 进程启动(一)

6.1 activityPaused(ActivityManagerService.java)

在章节5.5中的ActivityManagerNative.getDefault().activityPaused(token),这个函数的意思是告诉AMS,上一个应用已经完成OnPause了,接下去的工作可以继续下去。

    public final void activityPaused(IBinder token) {        //...        //调用的是ActivityStack的activityPausedLocked,第二个参数timeout==false        stack.activityPausedLocked(token, false);        //...    }

其中token是上一个应用的Ibinder对象,我们认为是launcher就行了

6.2 activityPausedLocked(ActivityStack.java)

1) 通知launcher自身Stack栈中的activityPausedLocked,当前已经完成pause暂停操作了,可以将之前章节5.4中说的PAUSE_TIMEOUT_MSG超时去掉。
2) mPausingActivity也是在章节5.4开始暂停的时候设置的,如果发现真正暂停的应用和完成暂停的应用是一个,代表暂停完成,调用completePauseLocked,并传递resumeNext==true,代表需要resume下一个应用

    //AMS调用的timeout==false    final void activityPausedLocked(IBinder token, boolean timeout) {        //代表该task仍在堆栈中,此时launcher是launcher的paused        final ActivityRecord r = isInStackLocked(token);        if (r != null) {            //pause已经完成,不需要PAUSE_TIMEOUT_MSG了            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);            //之前在startPausingLocked的时候设置了当前pause的应用,            //这个时候AMS返回代表pause成功,会进入这里            if (mPausingActivity == r) {                //pause成功,传递的参数是resumeNext==true,代表需要resume下一个应用                completePauseLocked(true);                return;            } else {            ...    }

6.3 completePauseLocked(true)

1) mWaitingVisibleActivities这里代表的是需要隐藏的可视界面,到目前为止我们没有设置过,这个是在第二次进入章节5.2 resumeTopActivityInnerLocked的时候才会设置。(准备resume恢复下一个应用test2,上一个应用launcher就会放入等待隐藏的列表mWaitingVisibleActivities中)
2) 非睡眠或者关机状态的时候会进入下一个activity的resume操作resumeFocusedStackTopActivityLocked
3) 最后ensureActivitiesVisibleLocked(ActivityStackSupervisor.java/ActivityStack.java)会更新界面相关操作,属于WMS范畴,本文不过多涉及
{

    //启动进程后会更新界面,此处仅仅把流程列出来,由于这篇文章本身太长了,不想在额外增加内容    ensureActivitiesVisibleLocked        ->ensureActivityConfigurationLocked        ->makeVisibleAndRestartIfNeeded->startSpecificActivityLocked()        ->screenshotActivitiesLocked        ->makeInvisible->addToStopping->scheduleIdleLocked

}

    private void completePauseLocked(boolean resumeNext) {        //prev,mPausingActivity是launcher        ActivityRecord prev = mPausingActivity;        //prev是不等于null的会进来这里        if (prev != null) {            //state在startPausingLocked时设置了ActivityState.PAUSING,            //所以一般情况wasStopping都是false            final boolean wasStopping = prev.state == ActivityState.STOPPING;            //重新设置标志位是ActivityState.PAUSED,这个是已经暂停的状态            prev.state = ActivityState.PAUSED;            //一般情况launcher启动应用,prev.finishing==false,故不会进入这里面            if (prev.finishing) {                //...            //prev.app是launcher            } else if (prev.app != null) {                //pause com.android.launcher时,此处会进来,prev就是com.android.launcher,                //wasStopping==false,visible==true               //第一次进来时mWaitingVisibleActivities还没有prev(resumeTopActivityInnerLocked               //第二次运行是才会设置),故不会进来这个                if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) {                    //...                }                //这个是在pause之后重新启动,一般都是false                if (prev.deferRelaunchUntilPaused) {                    //...                //wasStopping==false,也不走这里                } else if (wasStopping) {                    //...                //由于visible==true,也不是在睡眠状态,这里也不会进来                } else if ((!prev.visible && !hasVisibleBehindActivity())                        || mService.isSleepingOrShuttingDownLocked()) {                    //...                }            } else {                //这里实在app在onpause过程中died掉才会进入,正常不会运行                prev = null;            }            if (prev != null) {                //如果界面是冻屏的话,由于界面不再可见,将移除冻屏状态                prev.stopFreezingScreenLocked(true /*force*/);            }            //mPausingActivity设置为null,此时pause已经全部完成            mPausingActivity = null;        }        //上面都是AMS进来的activityPausedLocked,resumeNext == true        if (resumeNext) {            //之前的moveActivityStackToFront中有设置过focus stack为test2            final ActivityStack topStack = mStackSupervisor.getFocusedStack();            //非睡眠或者关机会进入这里            if (!mService.isSleepingOrShuttingDownLocked()) {                //一般进入这里,会resume 下一个应用(next),                //同步的,执行了Process.start之后才会继续往下跑                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);            } else {            ...        }        if (prev != null) {            //重新恢复接收输入事件            prev.resumeKeyDispatchingLocked();            //如果是在使用电池            if (prev.app != null && prev.cpuTimeAtResume > 0                    && mService.mBatteryStatsService.isOnBattery()) {                //cpuTimeAtResume是在activity resume的时候设置的,                //代表从resume到pause的时间,将作为前台运行时间                long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)                        - prev.cpuTimeAtResume;                //...                //addForegroundTimeLocked这个是电量估算的时候用的,判断该activity前台运行的时常                if (ps != null) {                    ps.addForegroundTimeLocked(diff);                //...            }            //当前已经是onpause暂停了,清空进入resume的时间            prev.cpuTimeAtResume = 0;        }        //有界面可视的时候mAppVisibilitiesChangedSinceLastPause==true(setVisible时设置),        //所以这里会进来        if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause) {            //...            //launcher已经pause,设置mAppVisibilitiesChangedSinceLastPause==false            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;        }        //最后是更新显示界面,这里是第一次调用ensureActivitiesVisibleLocked,        //遍历所有stack的ensureActivitiesVisibleLocked        mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);    }

6.4 resumeFocusedStackTopActivityLocked/startSpecificActivityLocked(ActivityStackSupervisor.java)

resumeFocusedStackTopActivityLocked在章节5.1-5.2已经看过,此处传递的targetStack是test2,pre是launcher,resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java) -> resumeTopActivityUncheckedLocked(ActivityStack.java) -> resumeTopActivityInnerLocked -> startSpecificActivityLocked(ActivityStackSupervisor.java),启动的是next==test2

这里就不翻回去讲了,接下去讲startSpecificActivityLocked(ActivityStackSupervisor.java)这个启动应用的函数(注意此处是第一次进入,章节6.3提到的那一次是第二次进入,是在之后)

    //r==test2,andResume==true,checkConfig==true    void startSpecificActivityLocked(ActivityRecord r,            boolean andResume, boolean checkConfig) {        //...        //当进程都未启动时不走这里,thread肯定是null,热启动相关逻辑本次不讨论        if (app != null && app.thread != null) {            ...        }        //AMS中去启动进程        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,                "activity", r.intent.getComponent(), false, false, true);    }

6.5 startProcessLocked(ActivityManagerService.java)

重要看到startProcessLocked启动进程相关名字,这个是AMS的启动进程的api。
先关注第一次进入的逻辑:
1) 新建一个进程对象的实例new ProcessRecord,该对象可以代表一个进程
2) 判断应用是32位还是64位的,用于虚拟机参数配置
3) Process.start进程启动
4) event log写入am_proc_start,代表进程已经启动,这句话出来的时候应用进程已经创建

    //9个参数(r.processName==test2, r.info.applicationInfo, true, 0,     //"activity", r.intent.getComponent(), false, false, true)    final ProcessRecord startProcessLocked(String processName,            ApplicationInfo info, boolean knownToBeDead, int intentFlags,            String hostingType, ComponentName hostingName, boolean allowWhileBooting,            boolean isolated, boolean keepIfLarge) {        //注意此处entryPoint==null        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,                null /* crashHandler */);    }    //14个参数,新建ProcessRecord    final ProcessRecord startProcessLocked(String processName, ...) {        long startTime = SystemClock.elapsedRealtime();        ProcessRecord app;        //isolated(孤立应用)是false,knownToBeDead是true        if (!isolated) {            //第一次进来app肯定是null            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);            //...            //设置了后台运行,桌面启动应用一般都不会走这里            if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {                ...            } else {                //重新计算崩溃次数(crash大于等于2次服务将不会再启动)                mAppErrors.resetProcessCrashTimeLocked(info);                //...            }        }        //这个是用来设置启动进程时cpu的策略,可以加快app启动速度        //默认没有用到,需要设置USE_SCHED_BOOST才会生效        nativeMigrateToBoost();        //3s钟后会关闭启动进程的cpu策略,同样此处默认没有用到        mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);        //第一次进入时没有启动过app/thread是null,pid是没有的.        //第二次进来时此处app是有了,pid也生成了,但是thread还没有        //第一次没启动不走这里,第二次会进来        if (app != null && app.pid > 0) {            //knownToBeDead是true,第二次进来app.thread还是null,故会进来,            //第二次是从章节6.3中ensureActivitiesVisibleLocked调用过来的            if ((!knownToBeDead && !app.killed) || app.thread == null) {                //第二次进程已经创建了,直接返回                //...                return app;            }            //...        }        //...        //第一次走这里,app是null        if (app == null) {            //这个是google的,用于调试卡顿的,不过除了特别有问题一般情况不会出现问题,            //50ms去掉系统或许更快,如果是给用户的稳定版本可以考虑把这段调试代码删除            checkTime(startTime, "startProcess: creating new process record");            //此处是new ProcessRecord            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);            //...            //新建ProcessRecord完成,该监控操作(newProcessRecordLocked)完成            checkTime(startTime, "startProcess: done creating new process record");        }        //监控进程启动的时常是否超时        checkTime(startTime, "startProcess: stepping in to startProcess");        //这里才是真正的启动进程的地方        startProcessLocked(                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);        checkTime(startTime, "startProcess: done starting proc!");        //如果有pid产生代表进程创建完成        return (app.pid != 0) ? app : null;    }    //真正启动进程的地方    private final void startProcessLocked(ProcessRecord app, String hostingType,            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {        //...        if (app.pid > 0 && app.pid != MY_PID) {//第一次启动app.pid == -1,不走这里            ...        }        //...        updateCpuStats();//启动进程也会更新CPU状态        try {            try {                //用于检测是否可以启动,如:是否安装,是否正在冻屏等                AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);            }            //isolated初始值是false            if (!app.isolated) {                //...                //返回应用用户组的gid,如果是uid不一样,同一个应用该值也会不一样                permGids = pm.getPackageGids(app.info.packageName,                        MATCH_DEBUG_TRIAGED_MISSING, app.userId);                MountServiceInternal mountServiceInternal = LocalServices.getService(                        MountServiceInternal.class);                //获取应用读写外部存储的权限                //如果是孤立应用(uid是99000-99999)将返回MOUNT_EXTERNAL_NONE;                //能读返回MOUNT_EXTERNAL_READ,能写返回MOUNT_EXTERNAL_WRITE                mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,                        app.info.packageName);                //...            }            //...            //android:multiArch="true"代表所有架构都支持,一般都不设置,            //一般应用库文件需要判断是否32位还算64位,判断方法使用            //com_android_internal_content_NativeLibraryHelper.cpp的findSupportedAbi            //requiredAbi就是为了兼容32位&64位系统设计的            String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;            if (requiredAbi == null) {                //此处如果应用没有设置实在32位还是64位运行的化,                //默认使用属性值ro.product.cpu.abilist的第一个值arm64-v8a(64bit),                //armeabi-v7a(32bit),armeabi(32bit)                requiredAbi = Build.SUPPORTED_ABIS[0];            }            String instructionSet = null;            if (app.info.primaryCpuAbi != null) {                //通过应用的库文件获取虚拟机要使用那种参数                instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);            }            //上面传递的entryPoint==null,isActivityProcess==true            boolean isActivityProcess = (entryPoint == null);            //将ActivityThread作为应用默认的入口函数entryPoint            if (entryPoint == null) entryPoint = "android.app.ActivityThread";            //此处才是调用Process.start启动进程的地方            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);//此处才是调用Process.start启动进程的地方            //此处就是event log中am_proc_start            EventLog.writeEvent(EventLogTags.AM_PROC_START,                    UserHandle.getUserId(uid), startResult.pid, uid,                    app.processName, hostingType,                    hostingNameStr != null ? hostingNameStr : "");            //设置进程的pid            app.setPid(startResult.pid);            //一般usingWrapper==false            app.usingWrapper = startResult.usingWrapper;            //代表正在运行            app.removed = false;            app.killed = false;            //代表没有给AMS杀死            app.killedByAm = false;            synchronized (mPidsSelfLocked) {                //process start之后就会有pid了,此处是test2.com.myapplication的pid会生成                //会将该pid放入AMS的pid列表中                this.mPidsSelfLocked.put(startResult.pid, app);                if (isActivityProcess) {//isActivityProcess==true                    //10s没有启动将不再启动,该app,Process.start虚拟机进程创建是同步的,                    //但是attachApplicationLocked是异步的,在attachApplication的时候                    //会remove这个超时PROC_START_TIMEOUT_MSG                    mHandler.sendMessageDelayed(msg, startResult.usingWrapper                            ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);                ...    }

7. 进程启动(二)Process.start

Process.start这个是新建进程通用的系统方法,代码位置:
frameworks/base/core/java/android/os/Process.java。
接下去从这个开始,这里面大家熟悉的内容可能更多。

进程启动(二)
图7.1 进程启动(二)

7.1 Process.start(Process.java)

我们注意传递的参数processClass是android.app.ActivityThread,niceName是processName,debugFlags一般都是等于0,mountExternal代表是否可读写外部存储,targetSdkVersion是这个应用的targetSdkVersion,seInfo是签名相关(默认是”default”),abi是这个应用要运行的cpu架构(32还是64位),instructionSet是指的是arm或者arm64,appDataDir一般指的是/data这个目录,zygoteArgs==null。

后面这些参数都会有用到,对于理解流程有很大的帮助。

    //processClass是android.app.ActivityThread,niceName是processName,    //debugFlags一般都是等于0,mountExternal代表是否可读写外部存储,    //targetSdkVersion是这个应用的targetSdkVersion,seInfo是签名相关(默认是”default”),    //abi是这个应用要运行的cpu架构(32还是64位),instructionSet是指的是arm或者arm64,    //appDataDir一般指的是/data这个目录,zygoteArgs==null    public static final ProcessStartResult start(final String processClass,                                  final String niceName,                                  int uid, int gid, int[] gids,                                  int debugFlags, int mountExternal,                                  int targetSdkVersion,                                  String seInfo,                                  String abi,                                  String instructionSet,                                  String appDataDir,                                  String[] zygoteArgs) {        try {            //通过虚拟机来创建新的进程            return startViaZygote(processClass, niceName, uid, gid, gids,                    debugFlags, mountExternal, targetSdkVersion, seInfo,                    abi, instructionSet, appDataDir, zygoteArgs);        //...    }

7.2 startViaZygote-> zygoteSendArgsAndGetResult

1) startViaZygote通将参数全部转化成Zygote的数组String
2) openZygoteSocketIfNeeded/zygoteSocket.connect创建Socket链接,并获取输入输出流对象
3) zygoteSendArgsAndGetResult通过Socket与底层交互,传递相应的事件内容,并获取返回的结果

    private static ProcessStartResult startViaZygote(final String processClass,        //...        ArrayList<String> argsForZygote = new ArrayList<String>();        //...添加虚拟机参数        //最后添加的是ActivityThread应用的入口类        argsForZygote.add(processClass);        //extraArgs==null,所以后面没有参数了        if (extraArgs != null) {            for (String arg : extraArgs) {                argsForZygote.add(arg);            }        }        //注意openZygoteSocketIfNeeded是connect Socket,        //zygoteSendArgsAndGetResult是向Socket传递参数        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);    }    private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {            try {                //ZYGOTE_SOCKET的名字是"zygote",连接socket                primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);            //...    }    public static ZygoteState connect(String socketAddress) throws IOException {        //...        try {            //这里是connect的地方,会通知相应的链接对象            zygoteSocket.connect(new LocalSocketAddress(socketAddress,                    LocalSocketAddress.Namespace.RESERVED));            //输入流,是用来读东西的,例如设备有数据输出,然后我们读取            zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());            //输出流是用来写东西的,例如写东西然后输出到什么位置            zygoteWriter = new BufferedWriter(new OutputStreamWriter(                    zygoteSocket.getOutputStream()), 256);        //...    }    private static ProcessStartResult zygoteSendArgsAndGetResult(            ZygoteState zygoteState, ArrayList<String> args)            throws ZygoteStartFailedEx {        try {            //...           //第一个先写的是参数大小            writer.write(Integer.toString(args.size()));            writer.newLine();            for (int i = 0; i < sz; i++) {                String arg = args.get(i);                //传递设置参数                writer.write(arg);                writer.newLine();            }            //清空输出流,并写入,运行完成之后代表写入成功,此时Socket会接受到相应消息            writer.flush();            //...            //读取返回的pid数据            result.pid = inputStream.readInt();            //读取返回的usingWrapper数据            result.usingWrapper = inputStream.readBoolean();            ...    }

7.3 ZygoteInit.main(ZygoteInit.java)

1) 开机运行app_process进程(init.zygote*.rc->app_process)->app_main.main->ZygoteInit.main,Zygote受精卵进程是由init进程创建,如下通过ps可知:init进程是Zygote64受精卵进程的父进程,而system_server是通过zygote64受精卵进程创建的。(pid是该进程的id,ppid是其父进程的id)

USER      PID   PPID  VSIZE  RSS   WCHAN              PC  NAMEroot      1     0     28524  1932  SyS_epoll_ 0000000000 S /initroot      428   1     1771768 22020 poll_sched 0000000000 S zygote64   //此处代表是64bit的system    996   428   2086288 190084 SyS_epoll_ 0000000000 S system_server

2) 获取当前操作系统的32&64位架构abiList,这个在socket connect的时候用于
2) 注册zygote的LocalServerSocket对象(Socket的服务端,可以给别人connect)
3) 启动系统服务startSystemServer
4) 等待Socket消息的通知来执行相应的任务runSelectLoop
5) MethodAndArgsCaller的run方法

    //开机运行app_process进程(init.zygote*.rc->app_process)->app_main.main->ZygoteInit.main    public static void main(String argv[]) {        //...        try {            //Socket的名字是zygote            String socketName = "zygote";            String abiList = null;             for (int i = 1; i < argv.length; i++) {                //第一次进来会设置startSystemServer==true                if ("start-system-server".equals(argv[i])) {                    startSystemServer = true;                } else if (argv[i].startsWith(ABI_LIST_ARG)) {                    //读的是系统属性ro.product.cpu.abilist64或者ro.product.cpu.abilist32里面的值                    abiList = argv[i].substring(ABI_LIST_ARG.length());                //...            //android的Socket名字:ANDROID_SOCKET_ + zygote            registerZygoteSocket(socketName);            //event log中会出现boot_progress_preload_start            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,                SystemClock.uptimeMillis());            //重新加载Cache,Classes,Resources,OpenGL,SharedLibraries,            //TextResources,WebView,AndroidKeyStoreProvider            preload();            //event log中会出现boot_progress_preload_end            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,                SystemClock.uptimeMillis());            //...            //做GC,清除一些软引用对象            gcAndFinalize();            //...            //在初始化时unmount根目录"/storage"            Zygote.nativeUnmountStorageOnInit();            //允许zygote创建进程            ZygoteHooks.stopZygoteNoThreadCreation();            //如果需要启动系统服务则进入这里            if (startSystemServer) {                //启动系统服务system_server,先后调用fork顺序是init                //->zygote64(64位系统)->system_server,如果是系统进程的话,                //这里是永远不会返回的startSystemServer->handleSystemServerProcess                //->RuntimeInit.zygoteInit->SystemServer.main/run->Looper.loop()                //->(pollInner/epoll_wait)Looper.cpp,                //这个除了Loop里面调用mQueue.quit是不会退出的                startSystemServer(abiList, socketName);             }            //会跑下来的是zygote进程,zygote进程会一直在此运行            runSelectLoop(abiList);            closeServerSocket();        } catch (MethodAndArgsCaller caller) {            //对于此处zygote frok的子进程会进入此处,抛出MethodAndArgsCaller异常,            //会执行run方法,其实是反射调用ActivityThread.main,这个后面会讲到            caller.run();        //...    }

ps: Zygote进程是用来fork各个子进程的,如system_server就是其创建的,其中zygote64是所有64位进程的父进程,zygote是所有32位进程的父进程。

7.4 runSelectLoop

runSelectLoop循环等待Socket的数据反馈,这里写的是Select的Loop,目前androidN使用的方法是Os.poll不再有1024个Socket的限制(androidL和之前的版本使用的是select方法),后续android版本升级的话可能使用epoll(目前上层的Looper、MessageQueue就是使用epoll)

1) 循环遍历等待Socket缓冲区有可读的数据
2) Socket.connect时会创建新的ZygoteConnection
3) ZygoteConnection执行runOnce
4) 创建子进程后,子进程退出循环,父进程继续等待下一个Socket数据

    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {        //...        // sServerSocket是AMS Process.java中的ZYGOTE_SOCKET链接的对象, 用来创建进程        //sServerSocket是LocalServerSocket,代表整个socket        //fds是所有zygote Socket相关的文件描述符        fds.add(sServerSocket.getFileDescriptor());        //peers是ZygoteConnection对象,是zygote链接之后的对象        peers.add(null);        while (true) {            //...            //events代表等待的事件类型,POLLIN类型代表我们只关心缓冲区是否有数据可读            pollFds[i].events = (short) POLLIN;            //...            try {                //poll函数与select类似都是,可以监视多个描述符,-1代表永不超时,                //轮询一遍之后等待,当设备驱动发生自身资源可读写后,会唤醒其等待队列上睡眠的进程                Os.poll(pollFds, -1);            }            //...            for (int i = pollFds.length - 1; i >= 0; --i) {                //revents域是文件描述符的操作结果事件掩码,POLLIN代表有数据可读                if ((pollFds[i].revents & POLLIN) == 0) {                    continue;                }                //i==0是就是外部有创建socket的时候,如Socket.connect,                //这个时候Os.poll中LocalServerSocket会有数据返回,                //此时LocalServerSocket会accept并创建新的ZygoteConnection                if (i == 0) {                    //创建新的受精卵的Socket链接ZygoteConnection                    ZygoteConnection newPeer = acceptCommandPeer(abiList);                    //添加到ZygoteConnection数组peers                    peers.add(newPeer);                    //添加到zygote Socket相关的文件描述符数组中去                    fds.add(newPeer.getFileDesciptor());                //非第一次运行时,如果之前创建的Socket链接对象ZygoteConnection有数据可以读,                //如OutputStream(zygoteWriter就是输出流)有写入,那么此处会有数据,                //进入runOnce函数。                } else {                    //创建子进程会抛出MethodAndArgsCaller的异常,                    //给ZygoteInit.main捕获,然后运行ActivityThread的main函数,                    //子进程抛出异常后退出该循环,但是Zygote父进程还算会继续循环的                    boolean done = peers.get(i).runOnce();                    //创建子进程后,父进程也就是zygote进程才会进入这里                    //...                }            }        }    }

runSelectLoop函数就是在监听Socket端是否有数据可以读,如果有数据来了,那么就是创建进程,这个Zygote进程主要作用就是创建进程(子进程的一些基本信息都不用再初始化,因为Zygote已经初始过了,相当于优化了启动进程的流程)。

7.5 runOnce(ZygoteConnection.java)

1) 读取相应的参数列表
2) 创建子进程forkAndSpecialize(Zygote.forkAndSpecialize -> com_android_internal_os_Zygote_nativeForkAndSpecialize/ForkAndSpecializeCommon/fork(com_android_internal_os_Zygote.cpp)),通过jni调用com_android_internal_os_Zygote_nativeForkAndSpecialize,最后调用的是fork函数,该函数用于创建进程,具体在这里不展开,具体可以参考之前的一篇文章Android上层如何调用一个底层函数的章节2.1.3 com_android_internal_os_Zygote.cpp本地函数里面有关于fork的讲解。最终子进程返回的是pid==0,父进程返回的是子进程的pid。
3) 处理父进程的内容handleParentProc,如返回给AMS章节6.5中startProcessLocked的Process.start,其值是Process.ProcessStartResult startResult,包含子进程pid
4) 处理子进程的内容handleChildProc,这个放在下一节讲解

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {        ...        try {            //读取相应的参数列表            args = readArgumentList();            descriptors = mSocket.getAncillaryFileDescriptors();        }        //...        //invokeWith==null,目前没有设置        if (parsedArgs.invokeWith != null) {            //...        }        //...        int [] fdsToClose = { -1, -1 };        FileDescriptor fd = mSocket.getFileDescriptor();        if (fd != null) {            //客户端的文件描述符            fdsToClose[0] = fd.getInt$();        }        fd = ZygoteInit.getServerSocketFileDescriptor();        if (fd != null) {            //服务端的文件描述符            fdsToClose[1] = fd.getInt$();        }        //调用native fork进程的地方        //此处是fock进程(Zygote.forkAndSpecialize        //->com_android_internal_os_Zygote_nativeForkAndSpecialize        //->ForkAndSpecializeCommon/fork(com_android_internal_os_Zygote.cpp))        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,                parsedArgs.appDataDir);        //...        try {            //如果是子进程pid会等于0,父进程此处pid会返回子进程的pid            if (pid == 0) {                //...                //处理子进程逻辑                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);                //子进程是永远不会到这个位置来的,因为之前已经抛出MethodAndArgsCaller异常                return true;            } else {                //...                //处理父进程逻辑                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);            }        ...    }    private String[] readArgumentList()            throws IOException {        //...        try {            //读取第一个参数            String s = mSocketReader.readLine();            //第一个参数上面章节7.2 Process.java中zygoteSendArgsAndGetResult写的就是参数个数            argc = Integer.parseInt(s);        }        //传递的参数最多是1024个,超过的话系统可能受到DOS攻击        if (argc > MAX_ZYGOTE_ARGC) {            throw new IOException("max arg count exceeded");        }        for (int i = 0; i < argc; i++) {            //读出每一个参数返回result数组中去            result[i] = mSocketReader.readLine();            ...    }    private boolean handleParentProc(int pid,            FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) {        if (pid > 0) {            //如果返回的pid大于0,说明子进程创建成功,此时设置子进程的pid            setChildPgid(pid);        }        //...        try {            //传递pid回去,最后写入章节7.2中zygoteSendArgsAndGetResult的result.pid            mSocketOutStream.writeInt(pid);            //传递是否wrapped进程,此处一般都是false            mSocketOutStream.writeBoolean(usingWrapper);        }        //...        return false;    }

8. 绑定进程am_proc_bound

上一章节我们知道了Process.start用于创建进程,父进程会直接返回子进程的pid,那么接下去我们需要从子进程处理的内容开始分析,看看子进程是怎样关联到上层的application中去的,这里讲解第一步am_proc_bound

这里写图片描述
图8.1 绑定进程

8.1 handleChildProc(ZygoteConnection.java)

1) 关闭相应的子进程Socket链接
2) 设置进程的名字,这个时候通过ps就可以看到进程名字变成应用声明的进程(如果没有定义android:process那么默认该进程名字就是应用的包名)
3) RuntimeInit.zygoteInit子进程的初始化

    private void handleChildProc(Arguments parsedArgs,            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)            throws ZygoteInit.MethodAndArgsCaller {        //关闭自己的Socket        closeSocket();        //关闭ZygoteInit中服务端的Socket        ZygoteInit.closeServerSocket();        //...        if (parsedArgs.niceName != null) {            //自己设置自己的名字,此处设置进程名字为之前传进来的processName            Process.setArgV0(parsedArgs.niceName);        }        //这里是不运行的        if (parsedArgs.invokeWith != null) {            //...        //此处会进来        } else {            //运行初始化RuntimeInit中的进程(受精卵)初始化zygoteInit            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,                    parsedArgs.remainingArgs, null /* classLoader */);        }    }

ps:Process.setArgV0会通过prctl(PR_SET_NAME…),裁剪后(process_name.c),只保留processName后面15个字符(kernel实际还会裁剪到最后一个字符,其实是14个字符),设置进程名字(内核标识进程的名字是task_struc->comm).
进程的名字在某些地方显示不是无限长的,如在systrace显示的进程名字就不超过15个字符。

8.2 zygoteInit(RuntimeInit.java)

1) log重定向redirectLogStreams
2) 通用设置初始化commonInit
3) 初始化zygote:nativeZygoteInit
4) 应用初始化applicationInit

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        //重新定向log的输入地方,此处设置log输出到Android log中        redirectLogStreams();        //一些通用设置的初始化        commonInit();        //初始化zygote,这里AppRuntime继承的是AndroidRuntime,运行的是启动线程池startThreadPool        nativeZygoteInit();        //应用初始化,此处是接下来运行的地方        applicationInit(targetSdkVersion, argv, classLoader);    }    private static final void commonInit() {        //...        //设置默认的异常捕获        Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());        TimezoneGetter.setInstance(new TimezoneGetter() {            @Override            public String getId() {                //设置时区id                return SystemProperties.get("persist.sys.timezone");            }        });        //设置时区        TimeZone.setDefault(null);        LogManager.getLogManager().reset();        //Android log相关初始化        new AndroidConfig();        String userAgent = getDefaultUserAgent();        //网络用户代理初始化        System.setProperty("http.agent", userAgent);        //网络Socket相关        NetworkManagementSocketTagger.install();        //...        initialized = true;    }

8.3 applicationInit

1) 设置虚拟机GC回收比例,正在使用的对象/堆栈大小 = 0.75
2) 设置虚拟机sdk的版本号
3) 获取相应的参数,如args.startClass就是在章节7.2 startViaZygote设置的processClass(ActivityThread)
4) 通过反射查找ActivityThread的main函数,并将其作为MethodAndArgsCaller异常的参数

    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        //设置退出时不调用onExit()函数        nativeSetExitWithoutCleanup(true);        //设置GC回收后的比例,正在使用的对象/堆栈大小 = 0.75,对应于dalvik.vm.heaptargetutilization        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);        //设置sdk的版本号,这个是进程启动Process.start时就传递过来的        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);        //获取相应的参数,如args.startClass就是第一个非"--"开头的参数        final Arguments args;        try {            args = new Arguments(argv);        }        //...        //反射调用main函数,注意startClass是Process.start时传递进来的android.app.ActivityThread        invokeStaticMain(args.startClass, args.startArgs, classLoader);    }    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        //...        //查找android.app.ActivityThread类        cl = Class.forName(className, true, classLoader);        //...        //查找其中的main函数        m = cl.getMethod("main", new Class[] { String[].class });        //...        //获取函数的调用属性        int modifiers = m.getModifiers();        //必须是静态而且是public的方法,否则抛出RuntimeException异常        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {            throw new RuntimeException(                    "Main method is not public and static on " + className);        }        //抛出MethodAndArgsCaller异常        throw new ZygoteInit.MethodAndArgsCaller(m, argv);    }

在章节7.3 ZygoteInit.main方法里面有捕获MethodAndArgsCaller异常,并调用MethodAndArgsCaller的run方法。

8.4 MethodAndArgsCaller.run()

反射调用ActivityThread的main静态函数

   public static class MethodAndArgsCaller extends Exception            implements Runnable {        //...        public MethodAndArgsCaller(Method method, String[] args) {            //mMethod是ActivityThread的main方法            mMethod = method;            //mArgs一般都是null            mArgs = args;        }        public void run() {            try {                //调用方法method,传递的是args参数,传递第一个参数是类对象为null,代表静态函数                mMethod.invoke(null, new Object[] { mArgs });            //...

到这里进程已经启动完成,将进入应用相关流程

8.5 MethodAndArgsCaller.run()

1) 消息队列初始化Looper.prepareMainLooper
2) 新建ActivityThread并附着thread.attach
3) 进入消息队列的循环Looper.loop

    public static void main(String[] args) {        //默认是没有用到SamplingProfilerIntegration的,        //该类用于监听性能数据,包含进程名字、应用信息、线程启动与关闭,        //还有默认persist.sys.profiler_ms毫秒dump一次该进程堆栈信息        SamplingProfilerIntegration.start();        //在严格模式或者调试的时候打开,默认不打卡        CloseGuard.setEnabled(false);        //初始化环境(这里主要是存储设备的环境,用user id初始化)        Environment.initForCurrentUser();        //主要是libcore中使用event log的方法,Reporter的report类似于EventLog.writeEvent        EventLogger.setReporter(new EventLoggingReporter());        //配置文件目录在/data/misc/user/1000        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());        //设置认证相关的目录cacerts-added,cacerts-removed        TrustedCertificateStore.setDefaultUserDirectory(configDir);        //设置进程名字为<pre-initialized>,这个很快在handleBindApplication时就会给修改        Process.setArgV0("<pre-initialized>");        //消息队列初始化,主进程是不允许退出的,无法调用MessageQueue.quit退出        Looper.prepareMainLooper();        ActivityThread thread = new ActivityThread();        //新建一个ActivityThread并attach附着,这个跟接下去的attachApplication相关        thread.attach(false);        if (sMainThreadHandler == null) {            //获取thread的handler,将其作为应用的主线程            sMainThreadHandler = thread.getHandler();        }        if (false) {            //用户调试log,用于消息队列Message的事件分发log输出,            //调试消息队列的时候可以打开            Looper.myLooper().setMessageLogging(new                    LogPrinter(Log.DEBUG, "ActivityThread"));        }        //Looper.loop()里面是个for (;;)死循环,只要Message不为null,会一直运行        //Looper.loop() -> MessageQueue.next()         //-> nativePollOnce(android_os_MessageQueue.cpp)         //->(pollOnce/pollInner/epoll_wait) Looper.cpp,        //这个Message==null情况只有调用MessageQueue.quit才会发生,        //目前没有看到主动调用MessageQueue.quit,故这个消息队列循环是不会退出的        Looper.loop();        //如果进入到这里代表程序出错了,这里程序正常运行是不会进来的        throw new RuntimeException("Main thread loop unexpectedly exited");    }

在调用静态方法ActivityThread.main之后会新建一个ActivityThread对象,相当于该进程的主线程(UI线程),创建之后首先跑的就是ActivityThread的attach函数

8.6 attach

这里我们主要关注attachApplication,也就是AMS的应用附着即可

    private void attach(boolean system) {        //...        //是否system,应用启动肯定不是system,会进入此处        if (!system) {            //...            //设置ddms中的进程名字为"<pre-initialized>",临时的            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());            //设置ApplicationObject为ActivityThread            RuntimeInit.setApplicationObject(mAppThread.asBinder());            final IActivityManager mgr = ActivityManagerNative.getDefault();            try {                //此处就是attachApplication                mgr.attachApplication(mAppThread);            } catch (RemoteException ex) {                throw ex.rethrowFromSystemServer();            }            //Java允许在类中定义一个名为finalize()的方法。            //它的工作原理是:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法。            //并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存            //BinderInternal里面实现的是Object finalize,            //当资源释放的时候会调用finalize,然后会调用            BinderInternal.addGcWatcher(new Runnable() {                //ActivityThread对象没有再使用时会进行回收                @Override public void run() {                    if (!mSomeActivitiesChanged) {                        return;                    }                    Runtime runtime = Runtime.getRuntime();                    //这个是HeapGrowthLimit,正常应用虚拟机内存最大值dalvik.vm.heapgrowthlimit,                     //AndroidRuntime.cpp/runtime.cc/heap.cc                    long dalvikMax = runtime.maxMemory();                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();                    //当前使用内存,如果最大内存的3/4将进行activity的释放操作                    if (dalvikUsed > ((3*dalvikMax)/4)) {                        //...                        mSomeActivitiesChanged = false;                        try {                            //此处释放指的是activity的ondestroy,                            //目前可以destroy的activity是处于onstop状态的activity                            mgr.releaseSomeActivities(mAppThread);                        //...        //让DropBox在libcore可用        DropBox.setReporter(new DropBoxReporter());    }

8.7 attachApplication/attachApplicationLocked

1) 首先是ActivityManagerNative.java的attachApplication会传递ActivityThread和调用者的pid给到AMS的attachApplicationLocked
2) eventlog中设置服务绑定进程am_proc_bound,说明进程启动完成,而且该进程的主线程ActivityThread已经创建,并且通知到AMS中
3) ActivityThread的绑定应用bindApplication, 这个会在下面章节讲解
4) 由于我们这个例子是桌面启动应用,那么最后mStackSupervisor.attachApplicationLocked堆栈中的绑定应用会真正启动activity活动对象,这个会在下面章节讲解

    //ActivityManagerNative.java    public final void attachApplication(IApplicationThread thread) {        ...            attachApplicationLocked(thread, callingPid);        ...    //ActivityManagerService.java    private final boolean attachApplicationLocked(IApplicationThread thread,            int pid) {        //...        ProcessRecord app;        //调用者非系统进程,且调用者的pid大于0        if (pid != MY_PID && pid >= 0) {            synchronized (mPidsSelfLocked) {                //在进程启动Process.start后就将pid添加进入mPidsSelfLocked了(父进程调用)                //现在是子进程调用,这个时候已经添加                app = mPidsSelfLocked.get(pid);            //...        //app.thread还没有设置过,下面makeActive将进行设置,会将app.thread设置成        //IApplicationThread(在ActivityThread中),app.thread不为null了        if (app.thread != null) {            //...        }        //...        try {            AppDeathRecipient adr = new AppDeathRecipient(                    app, pid, thread);            //设置binder died掉之后的的回调地方是binderDied            thread.asBinder().linkToDeath(adr, 0);            //设置目前谁在监控死亡状态            app.deathRecipient = adr;        //...        //eventlog中设置服务绑定am_proc_bound        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);        //设置ProcessRecord的IApplicationThread(在ActivityThread中)        app.makeActive(thread, mProcessStats);        //默认设置一个adj        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;        //...        //用户更新电量估算mBatteryStatsService的FOREGROUND时间        updateProcessForegroundLocked(app, false, false);        //...        //判断是否解锁        app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);        //去除进程启动超时的msg PROC_START_TIMEOUT_MSG,        //此处有ActivityThread回传,代表进程启动完成        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);        //一般情况normalMode都是true        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);        //generateApplicationProvidersLocked是开始创建应用的ContentProvider对象        List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;        //...        //一般不会进入这里,这里是自动化测试的时候会进来        if (app.instrumentationClass != null) {            //...        }        //...        //应用兼容性相关,该参数会传入AcitiviyThread中        app.compat = compatibilityInfoForPackageLocked(appInfo);        //一般profilerInfo==null        ProfilerInfo profilerInfo = profileFile == null ? null                : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);        //回到AcitiviyThread中的bindApplication,processName==test2,        //instrument相关都等于null,mBinderTransactionTrackingEnabled/        //enableTrackAllocation/isRestrictedBackupMode默认等于false,        //normalMode默认是true,persistent代表是否常驻内存,compat是兼容性相关,        //isolated==false,getCommonServicesLocked是将PMS、WMS、ALARM相关服务传入,        //mCoreSettingsObserver用于监听一些参数变化(长按超时,12/24小时显示时间变化,        //调试界面属性),bindApplication是异步的        thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,                profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,                app.instrumentationUiAutomationConnection, testMode,                mBinderTransactionTrackingEnabled, enableTrackAllocation,                isRestrictedBackupMode || !normalMode, app.persistent,                new Configuration(mConfiguration), app.compat,                getCommonServicesLocked(app.isolated),                mCoreSettingsObserver.getCoreSettingsLocked());        //将进程添加进入mLruProcesses中        //mLruProcesses保存的是正在运行应用的列表,第一个是最近使用的        updateLruProcessLocked(app, false, null);        //触发GC的时间重新计算        app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();        //...        //一般normalMode都是true        if (normalMode) {            try {                //如果是activity导致的进程启动,activity从这里开始启动                //此处用于am_restart_activity,此处设置了didSomething = true                if (mStackSupervisor.attachApplicationLocked(app)) {                    didSomething = true;                }            //...        //一般badApp==false        if (!badApp) {            try {                //如果之前该进程有需要启动的服务,此处开始启动服务                //启动进程了之后才会去启动服务                didSomething |= mServices.attachApplicationLocked(app, processName);        //...        if (!badApp && isPendingBroadcastProcessLocked(pid)) {            try {                //如果该进程之前有挂起的广播,现在可以开始发送了                didSomething |= sendPendingBroadcastsLocked(app);           // ...

到目前为止绑定进程的逻辑已经讲解完了,接下去我们仅需要关注thread.bindApplication和mStackSupervisor.attachApplicationLocked这2个函数

9 创建application

这一章节将会讲到application的实例化、application进程上下文context的创建、application的OnCreate

创建application
图9.1 创建application

9.1 bindApplication(ActivityThread.java)

我们关注的重点:
1) getPackageInfoNoCheck新建new LoadedApk,该类用于加载apk
2) makeApplication新建一个Application对象new newApplication(这里面会createAppContext创建application的进程上下文context)
3) callApplicationOnCreate调用Application的OnCreate

    private void handleBindApplication(AppBindData data) {        //设置art实时编译更加敏感,更新art配置相关信息的计数count会乘10=((10000/500)/2),        //会让art更容易更新配置(如做实时编译还是解释执行等)        VMRuntime.registerSensitiveThread();        //...        //设置process的启动时间,这个主要是给上层调用的        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());        //AMS传递进来的参数全部放在data上        mBoundApplication = data;        //进程启动时如果你没有设置固定方向或者手动改变方向,这个config就是AMS中的mConfiguration        mConfiguration = new Configuration(data.config);        mCompatConfiguration = new Configuration(data.config);        mProfiler = new Profiler();        //一般情况initProfilerInfo都是null,除了使用instrumentation(如自动化测试相关会使用到)        if (data.initProfilerInfo != null) {            ...        }        //此处会通过prctl(PR_SET_NAME...),裁剪后(process_name.c)        //只保留processName后面15个字符(kernel实际还会裁剪到最后一个字符,其实是14个字符),        //设置进程名字(内核标识进程的名字是task_struc->comm).        Process.setArgV0(data.processName);        //此处设置的是ddms调试使用的名字        android.ddm.DdmHandleAppName.setAppName(data.processName,                                                UserHandle.myUserId());        //常驻内存的进程        if (data.persistent) {            //如果在不能使用GPU加速(如低内存设备            //或者显示定义config_avoidGfxAccel为ture的情况都会进来)            if (!ActivityManager.isHighEndGfx()) {                //当前进程停止使用硬件渲染,这里的作用主要是为了减少运存RAM的消耗,                //对于低内存手机,这个是有帮助的                ThreadedRenderer.disable(false);            }        }        //...        //回复系统默认时区        TimeZone.setDefault(null);        //设置默认的语言        LocaleList.setDefault(data.config.getLocales());        //...        //新建new LoadedApk,该类用于加载apk        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);        //...        //可以通过config对分辨率进行设置,默认是没有设置的        updateDefaultDensity();        //设置是否24小时        final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));        DateFormat.set24HourTimePref(is24Hr);        //...        //网络代理相关设置        final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);        if (b != null) {            final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);            try {                final ProxyInfo proxyInfo = service.getProxyForNetwork(null);                Proxy.setHttpProxySystemProperty(proxyInfo);        //...        //新建一个appContext        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);        //...        //应用一般是isIsolated == false,这里讲的不是系统进程,是普通app的进程的启动,故会进入此处        if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {            //获取应用缓存目录,如("/data/user_de/0/com.android.settings/cache")            final File cacheDir = appContext.getCacheDir();            //...            //获取应用代码缓存目录,"/data/user_de/0/com.android.settings/code_cache"            //此处主要是存放的opengl和renderscript部分的缓存代码            //类似于com.android.opengl.shaders_cache、com.android.renderscript.cache这样的数据            final File codeCacheDir = deviceContext.getCodeCacheDir();        }        //...        //ii非自动化测试一般都是null        if (ii != null) {            ...        } else {            //一般情况下走的是这里            mInstrumentation = new Instrumentation();        }        //设置虚拟机堆栈最大能增长到的内存是多少,根据largeHeap属性判断是否大应用        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {            //如果是大应用的话,应用虚拟机内存可以增长到堆栈大小dalvik.vm.heapsize            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();        } else {            //默认只能增长到dalvik.vm.heapgrowthlimit受限制的堆栈大小            dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();        }        // allowThreadDiskWrites在应用oncreate的时候允许写的操作,        //返回的值是就得策略,此处仅用于临时修改        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();        try {            //restrictedBackupMode是flase,data.info是上面new的LoadedApk,            //这里面的createAppContext和上面的createAppContext传递的参数是一样的            //此处会新建一个Application对象new newApplication,此处是Application的实例化            //此处传递的第二个参数instrumentation==null,故application不会在此处OnCreate            Application app = data.info.makeApplication(data.restrictedBackupMode, null);            //保存当前的Application对象            mInitialApplication = app;            //一般没有限制备份模式,restrictedBackupMode == false            if (!data.restrictedBackupMode) {                //如果apk有provider就会进入这里(如静态注册的providers)                if (!ArrayUtils.isEmpty(data.providers)) {                    //初始化app中的所有provider                    installContentProviders(app, data.providers);                    //...                }            }            try {                //如果没有复写Instrumentation,一般此处没有做任何事情                mInstrumentation.onCreate(data.instrumentationArgs);            }            //...            try {                //此处调用的就是Application的OnCreate方法,                //activity的OnCreate后面会讲到,这里先调用的是Application的OnCreate                mInstrumentation.callApplicationOnCreate(app);            //...    }

9.2 getPackageInfoNoCheck/getPackageInfo

getPackageInfoNoCheck/getPackageInfo返回的是LoadedApk,用于加载apk

    public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,            CompatibilityInfo compatInfo) {        return getPackageInfo(ai, compatInfo, null, false, true, false);    }    //(ai, compatInfo, null, false, true, false);    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,            ClassLoader baseLoader, boolean securityViolation, boolean includeCode,            boolean registerPackage) {        //...        //此处apk是包含代码的,故是从mPackages取,第一次进来此处是null        ref = mPackages.get(aInfo.packageName);        LoadedApk packageInfo = ref != null ? ref.get() : null;        //新建LoadedApk加载apk的类        packageInfo =            new LoadedApk(this, aInfo, compatInfo, baseLoader,                    securityViolation, includeCode &&                    (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);        //...        //将新建的LoadedApk放到mPackages中        mPackages.put(aInfo.packageName,                new WeakReference<LoadedApk>(packageInfo));        //...        return packageInfo;    }

9.3 makeApplication(LoadedApk.java)

1) 创建Application的进程上下文
2) 调用代理Instrumentation新建Application
3) Application实例化、Application设置进程上下文context

    //LoadedApk.java    //forceDefaultAppClass==false,instrumentation==null    public Application makeApplication(boolean forceDefaultAppClass,            Instrumentation instrumentation) {        //...        Application app = null;        //如果应用没有重载Application类的话,直接使用默认的"android.app.Application"        String appClass = mApplicationInfo.className;        if (forceDefaultAppClass || (appClass == null)) {            appClass = "android.app.Application";        }        try {            java.lang.ClassLoader cl = getClassLoader();            //...            //创建Application的进程上下文            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);            //调用代理Instrumentation新建Application            app = mActivityThread.mInstrumentation.newApplication(                    cl, appClass, appContext);            appContext.setOuterContext(app);        }        //...        return app;    }    //Instrumentation.java    public Application newApplication(ClassLoader cl, String className, Context context)            throws InstantiationException, IllegalAccessException,             ClassNotFoundException {        return newApplication(cl.loadClass(className), context);    }    static public Application newApplication(Class<?> clazz, Context context)            ... {        //Application类的实例化,如类非静态变量等会在此处生成        Application app = (Application)clazz.newInstance();        //调用Application的attach附着,用于设置进程上下文context        app.attach(context);        return app;    }    //Application.java    final void attach(Context context) {        //设置base应用基本的进程上下文        attachBaseContext(context);        //设置类的加载器        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;    }

现在有了Application这个对象,下面接着会进行Application的OnCreate

9.4 callApplicationOnCreate(Instrumentation.java)

callApplicationOnCreate这个函数通过代理调用Application的OnCreate

    //Instrumentation.java    public void callApplicationOnCreate(Application app) {        app.onCreate();    }    //Application.java    public void onCreate() {    }

进程启动会先调用Application的OnCreate,这个也是算在应用启动生命周期内的。

目前Application创建了,Application的OnCreate也调用了,接下去就是Activity相关的逻辑。

阅读全文
0 0