AMS分析--基于深入理解android(3)

来源:互联网 发布:js实现多图上传 编辑:程序博客网 时间:2024/06/06 02:33
//将待启动的Activity放入栈顶  final void startActivityLocked(ActivityRecord r, boolean newTask,            boolean doResume, boolean keepCurTransition, Bundle options) {        TaskRecord rTask = r.task;        final int taskId = rTask.taskId;        if (taskForIdLocked(taskId) == null || newTask) {// 如果是新任务,则将任务插入到任务列表顶端            insertTaskAtTop(rTask);//将当前task置于顶部            mWindowManager.moveTaskToTop(taskId);        }        TaskRecord task = null;        if (!newTask) {            // If starting in an existing task, find where that is...            boolean startIt = true;            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {                task = mTaskHistory.get(taskNdx);                /// M: ALPS01315669, fix google KK bug, skip activity if it is finishing like JB @{                boolean findTask = false;                for (int index = task.mActivities.size() - 1; index >=0; --index) {                    ActivityRecord p = task.mActivities.get(index);                    if (p.finishing) {                        continue;                    }                    if (p.task == r.task) {                     //如果不是在新的ActivityTask(也就是TaskRecord)中的话,就找出要运行在的TaskRecord对象                        // Here it is!  Now, if this is not yet visible to the                        // user, then just add it without starting; it will                        // get started when the user navigates back to it.                        if (!startIt) {//默认情况下此处不执行                            if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "                                    + task, new RuntimeException("here").fillInStackTrace());                            task.addActivityToTop(r);                            r.putInHistory();                            /// M: Add for Activity Stack Parser @{                            if (null != mStackListener){                                mStackListener.dumpStack(mTaskHistory);                            }                            /// @}                            mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,                                    r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,                                    (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,                                    r.userId, r.info.configChanges);                            if (VALIDATE_TOKENS) {                                validateAppTokensLocked();                            }                            ActivityOptions.abort(options);                            return;                        }                        findTask = true;                        break;                    } else if (p.fullscreen) {                        startIt = false;                    }                }                if (findTask) {                    break;                }                /// @}            }
if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {            mStackSupervisor.mUserLeaving = false;//当用户按Home键等操作使程序进入后台时 就会根据mUserLeaving=true,             //调用onUserLeaveHint(),            //onUserLeaveHint            //这个回调函数主要用来监听按Home键退出到桌面的动作,发生在onPause之前。在启动一个新的Activity时,             //ActivityStackSupervisor里会调用startActivityUncheckedLocked,在它里面会给mUserLeaving赋值。              //mUserLeaving用于指示当前activity退到后台时函数onUserLeaving是否被调用。            //可见,只有当设置了FLAG_ACTIVITY_NO_USER_ACTION标志时mUserLeaving才会为false,            //其他情况下mUserLeaving均为true,也就是onUserLeaveHint会被调用,注释里也说了onUserLeaveHint会在onPause之前被调用。            if (DEBUG_USER_LEAVING) Slog.v(TAG,                    "startActivity() behind front, mUserLeaving=false");        }//http://www.2cto.com/kf/201503/380568.html        task = r.task;
 final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");        // Find the first activity that is not finishing.        ActivityRecord next = topRunningActivityLocked(null);        // Remember how we'll process this pause/resume situation, and ensure        // that the state is reset however we wind up proceeding.        final boolean userLeaving = mStackSupervisor.mUserLeaving;//如果被置位说明这是被闹钟启动的话为true,        //处理FLAG_ACTIVITY_NO_USER_ACTION情况,如果该标志位为1,则表示并非是用户主观意愿启动的Activity        // 具体情况如来电、闹钟事件等,此时mUserLeaving为false        mStackSupervisor.mUserLeaving = false;        if (next == null) {//启动桌面            // There are no more activities!  Let's just start up the            // Launcher...            ActivityOptions.abort(options);            /// M: Power off alarm feature:            /// If mAlarmBoot is TRUE, that means this is alarm boot-up            /// We will skip to resume home activity until the Alarm activity is destroyed. @{            if (PowerOffAlarmUtility.isAlarmBoot()) {                Slog.v(TAG, "Skip to resume home activity!!");                return false;            }            /// @}            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();            return mStackSupervisor.resumeHomeActivity(prev);        }        next.delayedResume = false;        // If the top activity is the resumed one, nothing to do.        //如果next即是当前需要启动的Activity组件,并且其状态为resumed,则不需要进行任何操作        //,表示当前Activity组件已经处于启动和激活了        //mResumedActivity当前正在显示的Activity        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&                    mStackSupervisor.allResumedActivitiesComplete()) {            // 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, "resumeTopActivityLocked: Top activity resumed " + next);            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();            return false;        }        final TaskRecord nextTask = next.task;        final TaskRecord prevTask = prev != null ? prev.task : null;        if (prevTask != null && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) {            //上一个prev Task 不为null 并且上一个 pre  task 退出时候要启动home,并且 pre Activity已经结束且pre Activity是起始Activity            if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();            if (prevTask == nextTask) {//但是这 要启动的Task和pre  task是同一个。                ArrayList<ActivityRecord> activities = prevTask.mActivities;                final int numActivities = activities.size();                for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {                    final ActivityRecord r = activities.get(activityNdx);                    // r is usually the same as next, but what if two activities were launched                    // before prev finished?                    if (!r.finishing) {//此时应该这样理解  if (!r.finishing) 要找到要启动activity,因为只有要启动activity没有finishing,                    //一个task 可以有几个起始activity,由于当前要启动的activity 与prev.frontOfTask 不同。所以我们要重新设置frontOfTask                        r.frontOfTask = true;//栈底作为入口 activity                         break;                    }                }             } else if (prevTask != topTask()) {                // This task is going away but it was supposed to return to the home task.                // Now the task above it has to return to the home task instead.                final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;                mTaskHistory.get(taskNdx).mOnTopOfHome = true;//新任务代替返回home task            } else {                if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next");                return mStackSupervisor.resumeHomeActivity(prev);//启动home            }        } else {            /// M: Fix ALPS01260522            /// If there are some task (must contain pending finishing activity) with mOnTopOfHome above next activity,            /// we should resume home activity @{            boolean needResumeHome = false;            for (int taskIndex = mTaskHistory.size() - 1; taskIndex >= 0; taskIndex--) {                TaskRecord task = mTaskHistory.get(taskIndex);                if (next.task == task || task.mMovingToFront) {//在这种情况下。正在启动的task就是当前task,此时不需要启动home                    break;                } else if (task.mOnTopOfHome) {//若当前mOnTopOfHome = true 表示返回的时候启动home                    Slog.d(TAG, "Find previous pending finishing task with mOnTopOfHome: " + task);                    needResumeHome = true;                    break;                }            }            if (needResumeHome) {                Slog.d(TAG, "resumeTopActivityLocked: Launching home due to previous pending finishing task");                return mStackSupervisor.resumeHomeActivity(prev);            }

if (mService.isSleepingOrShuttingDown()
&& mLastPausedActivity == next
&& mStackSupervisor.allPausedActivitiesComplete()) {
// 如果当前的next是要显示的Activity,而且上次刚暂停的Activity正好也是next,并且系统正要进入关机或者睡眠状态
//说明系统要睡眠。
// 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, “resumeTopActivityLocked: Going to sleep and all paused”);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}

    // 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) {//判断当前要resume的Activity所属的userID是否已经起来        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);//next是要马上启动的。所以从mStoppingActivities 移除    mStackSupervisor.mGoingToSleepActivities.remove(next);//同理以上    next.sleeping = false;    mStackSupervisor.mWaitingVisibleActivities.remove(next);

//如果要resume一个Activity,那么必然要清掉mStoppingActivities、mGoingToSleepActivities、mWaitingVisibleActivities列表中该Activity
next.updateOptionsLocked(options);

    if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);    // If we are currently pausing an activity, then don't do anything    // until that is done.    if (!mStackSupervisor.allPausedActivitiesComplete()) {//再暂停完pre Activity之前,我们什么都不做        if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,                "resumeTopActivityLocked: Skip resume: some activity pausing.");        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();        return false;    }

boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
//前面说了,在调用resumeTopActivityLocked()已经做好了Stack、Task等准备,但是还没pause 前一个Stack中的resumed Activity
//,或者没有pause掉本Stack中resumed activity。此时便进行触发pause操作
//,然后返回,等待pause完成后调用completePauseLocked()–>resumeTopActivityLocked()再次尝试resume,此时便可继续往下执行。
//mStackSupervisor.mUserLeaving的值在过程5中被设置为true,此处取出来赋值给userLeaving
//,表明是用户操作行为(按下返回键,HOME按键等);无论是true还是false,此处还是再复位一下
//,重新设置为false
if (mResumedActivity != null) {
pausing = true;
startPausingLocked(userLeaving, false);
if (DEBUG_STATES) Slog.d(TAG, “resumeTopActivityLocked: Pausing ” + mResumedActivity);
}
if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
“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) {
// No reason to do full oom adj update here; we’ll let that
// happen whenever it needs to later.
mService.updateLruProcessLocked(next.app, true, null);
//调整进程调度优先级和OOM_Adj
//参考http://blog.csdn.net/yujun411522/article/details/46682687
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}

    if (mService.mSleeping && mLastNoHistoryActivity != null &&            !mLastNoHistoryActivity.finishing) {        if (DEBUG_STATES) Slog.d(TAG, "no-history finish of " + mLastNoHistoryActivity +                " on new resume");        requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,                null, "no-history", false);//确认 在mLastNoHistoryActivity 列表的Activity都已经被结束        mLastNoHistoryActivity = null;        //例如现在栈情况为:A B C。C通过intent跳转到D,这个intent添加FLAG_ACTIVITY_NO_HISTORY标志        //,则此时界面显示D的内容,但是它并不会压入栈中。如果按返回键,返回到C,栈的情况还是:A B C        //。如果此时D中又跳转到E,栈的情况变为:A B C E,此时按返回键会回到C,因为D根本就没有被压入栈中。    }    if (prev != null && prev != next) {        if (!prev.waitingVisible && next != null && !next.nowVisible) {            prev.waitingVisible = true;            //prev 置位true表示等待 next显示。nowVisible 表示 next要显示            mStackSupervisor.mWaitingVisibleActivities.add(prev);            if (DEBUG_SWITCH) Slog.v(                    TAG, "Resuming top, waiting visible to hide: " + prev);        } else {            // 如果当前Activity已经是可见,所以我们需要立即hide之间的Activity界面以便能够尽快地显示新Activity界面            if (prev.finishing) {                mWindowManager.setAppVisibility(prev.appToken, false);                if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "                        + prev + ", waitingVisible="                        + (prev != null ? prev.waitingVisible : null)                        + ", nowVisible=" + next.nowVisible);            } else {                if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "                    + prev + ", waitingVisible="                    + (prev != null ? prev.waitingVisible : null)                    + ", nowVisible=" + next.nowVisible);            }        }    }    // Launching this app's activity, make sure the app is no longer    // considered stopped.    //启动新Activity    try {        AppGlobals.getPackageManager().setPackageStoppedState(                next.packageName, false, next.userId); /* TODO: Verify if correct userid */    } catch (RemoteException e1) {    } catch (IllegalArgumentException e) {        Slog.w(TAG, "Failed trying to unstop package "                + next.packageName + ": " + e);    }    //如果pre Activity已经被finish了,那么直接隐藏pre Activity的窗口好了。如果没有被finish呢    //?那就先不管,反正next Activity的窗口肯定会覆盖pre Activity的窗口之上    //。从这个逻辑可以看出一个Activity只有在finish掉时窗口才设为不可见,pause状态窗口是可见的    //,同时也可以知道Activity切换动画是在resume next Activity时启动的。    boolean anim = true;    if (prev != null) {        if (prev.finishing) {            if (DEBUG_TRANSITION) Slog.v(TAG,                    "Prepare close transition: prev=" + prev);            if (mNoAnimActivities.contains(prev)) {//不要钱过度动画                anim = false;                 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);                //prepareAppTransition 详细看云笔记            } else {                mWindowManager.prepareAppTransition(prev.task == next.task                        ? AppTransition.TRANSIT_ACTIVITY_CLOSE                        : AppTransition.TRANSIT_TASK_CLOSE, false);                //TRANSIT_ACTIVITY_CLOSE:关闭当前活动窗口,恢复同一个task中的上一个窗口                //TRANSIT_TASK_CLOSE:关闭当前活动窗口,回到上一个任务            }            mWindowManager.setAppWillBeHidden(prev.appToken);//pre v的Activity隐藏            mWindowManager.setAppVisibility(prev.appToken, false);        } else {            if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev);            if (mNoAnimActivities.contains(next)) {                anim = false;                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);            } else {                mWindowManager.prepareAppTransition(prev.task == next.task                        ? AppTransition.TRANSIT_ACTIVITY_OPEN                        : AppTransition.TRANSIT_TASK_OPEN, false);            }        }        if (false) {            mWindowManager.setAppWillBeHidden(prev.appToken);            mWindowManager.setAppVisibility(prev.appToken, false);        }    } else {        if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous");        if (mNoAnimActivities.contains(next)) {            anim = false;            mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);        } else {            mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);            //TRANSIT_ACTIVITY_OPEN:在同一task中在最顶端打开一个窗口        }    }    if (anim) {        next.applyOptionsLocked();//启动动画    } else {        next.clearOptionsLocked();    }

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);//设置启动时间
//如果该进程存在并且已经向ams注册
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0//FLAG_MULTIPROCESS 可以在多进程运行的话。就不需要
//重新启动进程
|| !”android”.equals(r.info.packageName)) {
// Don’t add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn’t make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);//启动这个进程
return;
} catch (RemoteException e) {
Slog.w(TAG, “Exception when starting activity ”
+ r.intent.getComponent().flattenToShortString(), e);
}

        // If a dead object exception was thrown -- fall through to        // restart the application.    }    mService.startProcessLocked(r.processName, 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) {
ProcessRecord app;
if (!isolated) {//是否单独进程
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
…….
if (app == null) {
//在ActivityManagerService中为新进程创建一个ProcessRecord实例
app = newProcessRecordLocked(info, processName, isolated);
if (app == null) {
Slog.w(TAG, “Failed making new process record for ”
+ processName + “/” + info.uid + ” isolated=” + isolated);
return null;
}
mProcessNames.put(processName, app.uid, app);//添加到进程列表中
if (isolated) {
mIsolatedProcesses.put(app.uid, app);//添加到单独进程列表中
}
} else {
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, mProcessStats);
}//添加包名到 当前进程包列表

private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
//当app的pid大于0并且pid不是AMS的话,就要把当前pid的进程从mPidsSelfLocked列表中移除,防止重复,因为后面我们还要加入
if (app.pid > 0 && app.pid != MY_PID) {
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
//PROC_START_TIMEOUT_MSG消息,这个消息是AMS用来控制app启动时间的,如果启动超时了就发出效果消息,下面我们会设置这个消息,现在需要取消之前设置的消息,防止干扰。
//接下来的逻辑:
}
app.setPid(0);//pid 置位0
//系统中所有应用进程(同时包括SystemServer)的ProcessRecord信息都保存在mPidsSelfLocked成员中
}

    if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,            "startProcessLocked removing on hold: " + app);    mProcessesOnHold.remove(app);    //mProcessesOnHold用于保存那些在系统还没有准备好就提前请求启动的ProcessRecord

public static ActivityThread systemMain() {
HardwareRenderer.disable(true);
ActivityThread thread = new ActivityThread();
thread.attach(true);
return thread;
}

public final void installSystemProviders(List<ProviderInfo> providers) {    if (providers != null) {        installContentProviders(mInitialApplication, providers);    }}public int getIntCoreSetting(String key, int defaultValue) {    synchronized (mResourcesManager) {        if (mCoreSettings != null) {            return mCoreSettings.getInt(key, defaultValue);        }        return defaultValue;    }}private static class EventLoggingReporter implements EventLogger.Reporter {    @Override    public void report (int code, Object... list) {        EventLog.writeEvent(code, list);    }}private class DropBoxReporter implements DropBox.Reporter {    private DropBoxManager dropBox;    public DropBoxReporter() {        dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);    }    @Override    public void addData(String tag, byte[] data, int flags) {        dropBox.addData(tag, data, flags);    }    @Override    public void addText(String tag, String data) {        dropBox.addText(tag, data);    }}public static void main(String[] args) {    /// M: Retrieve the information from AMS @{    if ( args != null && args.length == 4 ) {        if ( args[0].equals("enable") ) {            mEnableAppLaunchLog = true;        }        if ( args[1].equals("true") ) {            mIsUserBuild = true;        }        if ( args[2].equals("true") ) {            mBooted = true;        }        if (args.length >=4 && args[3].equals("true") ) {//Prevention args.length < 4, then exception.            mEnableLooperLog = true;        }        if (!mIsUserBuild) {            Slog.v(TAG, "MAIN-ARGS launch log: " + mEnableAppLaunchLog + ", user build: "                 + mIsUserBuild + ", booted: " + mBooted + ", looper log: " + mEnableLooperLog);        }    }    /// @}    logAppLaunchTime(TAG, "ActivityThread is created"); /// M: It's for debugging App Launch time    SamplingProfilerIntegration.start();    // CloseGuard defaults to true and can be quite spammy.  We    // disable it here, but selectively enable it later (via    // StrictMode) on debug builds, but using DropBox, not logs.    CloseGuard.setEnabled(false);    Environment.initForCurrentUser();    // Set the reporter for event logging in libcore    EventLogger.setReporter(new EventLoggingReporter());    Security.addProvider(new AndroidKeyStoreProvider());    Process.setArgV0("<pre-initialized>");//这只进程名字    Looper.prepareMainLooper();//准备主线程消息循环    ActivityThread thread = new ActivityThread();//创建一个ActivityThread对象    thread.attach(false);    if (sMainThreadHandler == null) {        sMainThreadHandler = thread.getHandler();    }    AsyncTask.init();    if (false) {        Looper.myLooper().setMessageLogging(new                LogPrinter(Log.DEBUG, "ActivityThread"));    }    /// M: ALPS00270724 message history mechanism @{    /// M: for build type revise @{    try {        /// M: Enable/disable ANR mechanism from adb command @{        if ( ENABLE_ALL_ANR_MECHANISM == Settings.System.getInt(mSystemContext.getContentResolver(), Settings.System.ANR_DEBUGGING_MECHANISM, 0)) {        //if(!IS_USER_BUILD){        /// M: for build type revise @}            ANRAppManager mANRAppManager = ANRAppManager.getDefault();            Looper.myLooper().setMessageLogging(mANRAppManager.newMessageLogger(mEnableLooperLog));        }    } catch (Exception e) {        Log.d(TAG, "set ANR debugging mechanism state fair " + e );    }    /// @}    /// M: Enable/disable ANR mechanism from adb command @}    Looper.loop();//主线程循环    throw new RuntimeException("Main thread loop unexpectedly exited");}
                                         UserHandle.myUserId());        //设置DDMS中临时现实的进程名.        RuntimeInit.setApplicationObject(mAppThread.asBinder());        IActivityManager mgr = ActivityManagerNative.getDefault();        try {            logAppLaunchTime(TAG, "attachApplication -> AMS"); /// M: It's for debugging App Launch time            mgr.attachApplication(mAppThread);             //调用AMS的attachApplication,mAppThread为ApplicationThread类型,        //它是应用进程和AMS交互的接口        } catch (RemoteException ex) {            // Ignore        }    } else {        // Don't set application object here -- if the system crashes,        // we can't display an alert, we just want to die die die.        android.ddm.DdmHandleAppName.setAppName("system_process",                                                UserHandle.myUserId());        try {            mInstrumentation = new Instrumentation();            ContextImpl context = new ContextImpl();            context.init(getSystemContext().mPackageInfo, null, this);            Application app = Instrumentation.newApplication(Application.class, context);            mAllApplications.add(app);            mInitialApplication = app;            app.onCreate();        } catch (Exception e) {            throw new RuntimeException(                    "Unable to instantiate Application():" + e.toString(), e);        }    }
private final boolean attachApplicationLocked(IApplicationThread thread,        int pid) {    // Find the application record that is being attached...  either via    // the pid if we are running in multiple processes, or just pull the    // next app record if we are emulating process with anonymous threads.    ProcessRecord app;    if (pid != MY_PID && pid >= 0) {        synchronized (mPidsSelfLocked) {            app = mPidsSelfLocked.get(pid);//根据pid查找对应 processrecord对象        }    } else {        app = null;    }

//如果该应用进程由AMS启动,则它一定在AMS中有对应的processrecord,先创建一个processrecord对象
//,才发命令给zygote.如果此处app==null,则表示AMS没有该进程的记录。需要杀死他
if (app == null) {
Slog.w(TAG, “No pending application record for pid ” + pid
+ ” (IApplicationThread ” + thread + “); dropping process”);
EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
if (pid > 0 && pid != MY_PID) {
Process.killProcessQuiet(pid);
} else {//说明是system_server进程。
try {
thread.scheduleExit();
} catch (Exception e) {
// Ignore exceptions.
}
}
return false;
}

    // If this application record is still attached to a previous    // process, clean it up now.   //对象不为空,表示该进程为旧的未被杀死的进程,系统不会重用   //,而是调用 handleAppDiedLocked() 处理.将app之前的各种connect 断开    if (app.thread != null) {        handleAppDiedLocked(app, true, true);    }
    } else {        app = null;    }

//如果该应用进程由AMS启动,则它一定在AMS中有对应的processrecord,先创建一个processrecord对象
//,才发命令给zygote.如果此处app==null,则表示AMS没有该进程的记录。需要杀死他
if (app == null) {
Slog.w(TAG, “No pending application record for pid ” + pid
+ ” (IApplicationThread ” + thread + “); dropping process”);
EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
if (pid > 0 && pid != MY_PID) {
Process.killProcessQuiet(pid);
} else {//说明是system_server进程。
try {
thread.scheduleExit();
} catch (Exception e) {
// Ignore exceptions.
}
}
return false;
}

    // If this application record is still attached to a previous    // process, clean it up now.   //对象不为空,表示该进程为旧的未被杀死的进程,系统不会重用   //,而是调用 handleAppDiedLocked() 处理.将app之前的各种connect 断开    if (app.thread != null) {        handleAppDiedLocked(app, true, true);    }    // Tell the process all about itself.    if (localLOGV) Slog.v(            TAG, "Binding process pid " + pid + " to record " + app);    final String processName = app.processName;    try {           /*      创建一个应用进程讣告接收对象。当应用进程退出时,该对象的binderDied将被调      用。这样,AMS就能做相应处理。binderDied函数将在另外一个线程中执行,其内部也会      调用handleAppDiedLocked。假如用户在binderDied被调用之前又启动一个进程,      那么就会出现以上代码中app.thread不为null的情况。这是多线程环境中常出现的      情况,不熟悉多线程编程的读者要仔细体会。      */        AppDeathRecipient adr = new AppDeathRecipient(                app, pid, thread);        thread.asBinder().linkToDeath(adr, 0);        app.deathRecipient = adr;    } catch (RemoteException e) {        app.resetPackageList(mProcessStats);        startProcessLocked(app, "link fail", processName);        return false;    }    EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);     //设置该进程的调度优先级和oom_adj等成员    app.makeActive(thread, mProcessStats);    app.curAdj = app.setAdj = -100;    app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;    app.forcingToForeground = null;    app.foregroundServices = false;    app.hasShownUi = false;    app.debugging = false;    app.cached = false;       //启动成功,从消息队列中撤销PROC_START_TIMEOUT_MSG消息    mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

//通过ApplicationThread和应用进程交互,调用其bindApplication函数
thread.bindApplication(processName, appInfo, providers,
app.instrumentationClass, profileFile, profileFd, profileAutoStop,
app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
// Check if a next-broadcast receiver is in this process…
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app); //发送广播
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it ‘bad’
badApp = true;
}
}

    // Check whether the next backup agent is in this process...    if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {        if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);        ensurePackageDexOpt(mBackupTarget.appInfo.packageName);        try {            thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,                    compatibilityInfoForPackageLocked(mBackupTarget.appInfo),                    mBackupTarget.backupMode);            //http://blog.csdn.net/liyuanjinglyj/article/details/46916337 有关备份        } catch (Exception e) {            Slog.w(TAG, "Exception scheduling backup agent creation: ");            e.printStackTrace();        }    }    if (badApp) {        // todo: Also need to kill application to deal with all        // kinds of exceptions.        handleAppDiedLocked(app, false, true);        return false;    }    if (!didSomething) {        updateOomAdjLocked();        //调整进程优先级,didSomething代表以上流程是否启动了其他activity组件。 updateOomAdjLocked根据组件多少        //调整 oom_adj数值。    }    return true;
  设置代表该应用进程的ProcessRecrod对象的一些成员变量,例如用于和应用进程交互的thread对象、进程调度优先级及oom_adj的值等。·  从消息队列中撤销PROC_START_TIMEOUT_MSG。至此,该进程启动成功,但是这一阶段的工作仅针对进程本身(如设置调度优先级,oom_adj等),还没有涉及和Activity启动相关的内容,这部分工作将在第二阶段完成。

private void handleBindApplication(AppBindData data)
{
mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);

    mProfiler = new Profiler();    mProfiler.profileFile = data.initProfileFile;    mProfiler.profileFd = data.initProfileFd;    mProfiler.autoStopProfiler = data.initAutoStopProfiler;    logAppLaunchTime(TAG, "handleBindApplication is called"); /// M: It's for debugging App Launch time    // send up app name; do this *before* waiting for debugger    Process.setArgV0(data.processName);//设置进程名    android.ddm.DdmHandleAppName.setAppName(data.processName,                                            UserHandle.myUserId());    if (data.persistent) {        // Persistent processes on low-memory devices do not get to        // use hardware accelerated drawing, since this can add too much        // overhead to the process.        if (!ActivityManager.isHighEndGfx()) {            HardwareRenderer.disable(false);//低内存禁止使用硬件加速        }    }    //启动性能统计    if (mProfiler.profileFd != null) {        mProfiler.startProfiling();    }    // If the app is Honeycomb MR1 or earlier, switch its AsyncTask    // implementation to use the pool executor.  Normally, we use the    // serialized executor as the default. This has to happen in the    // main thread so the main looper is set right.    if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {        AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);    }    /*     * Before spawning a new process, reset the time zone to be the system time zone.     * This needs to be done because the system time zone could have changed after the     * the spawning of this process. Without doing this this process would have the incorrect     * system time zone.     */     //设置 TimeZone    TimeZone.setDefault(null);    /*     * Initialize the default locale in this process for the reasons we set the time zone.     */    Locale.setDefault(data.config.locale);    /*     * Update the system configuration since its preloaded and might not     * reflect configuration changes. The configuration object passed     * in AppBindData can be safely assumed to be up to date     */    mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);    mCurDefaultDisplayDpi = data.config.densityDpi;    applyCompatConfiguration(mCurDefaultDisplayDpi);    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);    /**     * Switch this process to density compatibility mode if needed.     */      //如果没有设置屏幕密度,则为DENSITY_DEFAULT设置默认的屏幕密度    if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)            == 0) {        mDensityCompatMode = true;        Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);    }    updateDefaultDensity();    final ContextImpl appContext = new ContextImpl();    appContext.init(data.info, null, this);    if (!Process.isIsolated()) {        final File cacheDir = appContext.getCacheDir();        if (cacheDir != null) {            // Provide a usable directory for temporary files            System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());            setupGraphicsSupport(data.info, cacheDir);        } else {            Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");        }    }    /**     * For system applications on userdebug/eng builds, log stack     * traces of disk and network access to dropbox for analysis.     */    if ((data.appInfo.flags &         (ApplicationInfo.FLAG_SYSTEM |          ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {        StrictMode.conditionallyEnableDebugLogging();    }    /**     * For apps targetting SDK Honeycomb or later, we don't allow     * network usage on the main event loop / UI thread.     *     * Note to those grepping:  this is what ultimately throws     * NetworkOnMainThreadException ...     */    if (data.appInfo.targetSdkVersion > 9) {        StrictMode.enableDeathOnNetwork();    }    if (data.debugMode != IApplicationThread.DEBUG_OFF) {        // XXX should have option to change the port.        Debug.changeDebugPort(8100);        if (data.debugMode == IApplicationThread.DEBUG_WAIT) {            Slog.w(TAG, "Application " + data.info.getPackageName()                  + " is waiting for the debugger on port 8100...");            IActivityManager mgr = ActivityManagerNative.getDefault();            try {                mgr.showWaitingForDebugger(mAppThread, true);            } catch (RemoteException ex) {            }            Debug.waitForDebugger();            try {                mgr.showWaitingForDebugger(mAppThread, false);            } catch (RemoteException ex) {            }        } else {            Slog.w(TAG, "Application " + data.info.getPackageName()                  + " can be debugged on port 8100...");        }    }    // Enable OpenGL tracing if required    if (data.enableOpenGlTrace) {        GLUtils.setTracingLevel(1);    }    // Allow application-generated systrace messages if we're debuggable.    boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;    Trace.setAppTracingAllowed(appTracingAllowed);    /**     * Initialize the default http proxy in this process for the reasons we set the time zone.     */    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);    if (b != null) {        // In pre-boot mode (doing initial launch to collect password), not        // all system is up.  This includes the connectivity service, so don't        // crash if we can't get it.        IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);        try {            ProxyProperties proxyProperties = service.getProxy();            Proxy.setHttpProxySystemProperty(proxyProperties);        } catch (RemoteException e) {}    }    if (data.instrumentationName != null) {        InstrumentationInfo ii = null;        try {            ii = appContext.getPackageManager().                getInstrumentationInfo(data.instrumentationName, 0);        } catch (PackageManager.NameNotFoundException e) {        }        if (ii == null) {            throw new RuntimeException(                "Unable to find instrumentation info for: "                + data.instrumentationName);        }        mInstrumentationAppDir = ii.sourceDir;        mInstrumentationAppLibraryDir = ii.nativeLibraryDir;        mInstrumentationAppPackage = ii.packageName;        mInstrumentedAppDir = data.info.getAppDir();        mInstrumentedAppLibraryDir = data.info.getLibDir();        ApplicationInfo instrApp = new ApplicationInfo();        instrApp.packageName = ii.packageName;        instrApp.sourceDir = ii.sourceDir;        instrApp.publicSourceDir = ii.publicSourceDir;        instrApp.dataDir = ii.dataDir;        instrApp.nativeLibraryDir = ii.nativeLibraryDir;        LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,                appContext.getClassLoader(), false, true);        ContextImpl instrContext = new ContextImpl();        instrContext.init(pi, null, this);        try {            java.lang.ClassLoader cl = instrContext.getClassLoader();            mInstrumentation = (Instrumentation)                cl.loadClass(data.instrumentationName.getClassName()).newInstance();        } catch (Exception e) {            throw new RuntimeException(                "Unable to instantiate instrumentation "                + data.instrumentationName + ": " + e.toString(), e);        }        mInstrumentation.init(this, instrContext, appContext,               new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,               data.instrumentationUiAutomationConnection);        if (mProfiler.profileFile != null && !ii.handleProfiling                && mProfiler.profileFd == null) {            mProfiler.handlingProfiling = true;            File file = new File(mProfiler.profileFile);            file.getParentFile().mkdirs();            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);        }    } else {     //创建Instrumentation对象,在正常情况都再这个条件下执行        mInstrumentation = new Instrumentation();    }     //如果Package中声明了FLAG_LARGE_HEAP,则可跳过虚拟机的内存限制,放心使用内存    if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();    }    // Allow disk access during application and provider setup. This could    // block processing ordered broadcasts, but later processing would    // probably end up doing the same disk access.    final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();    try {        // If the app is being launched for full backup or restore, bring it up in        // a restricted environment with the base application class.         //创建一个Application,data.info为LoadedApk类型,在其内部会通过Java反射机制         //创建一个在该APK AndroidManifest.xml中声明的Application对象        Application app = data.info.makeApplication(data.restrictedBackupMode, null);        mInitialApplication = app;         //mInitialApplication保存该进程中第一个创建的Application        // don't bring up providers in restricted mode; they may depend on the        // app's custom Application class         //安装本Package中携带的ContentProvider        if (!data.restrictedBackupMode) {            List<ProviderInfo> providers = data.providers;            if (providers != null) {                installContentProviders(app, providers);                // For process that contains content providers, we want to                // ensure that the JIT is enabled "at some point".                mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);            }        }        // Do this after providers, since instrumentation tests generally start their        // test thread at this point, and we don't want that racing.        try {            mInstrumentation.onCreate(data.instrumentationArgs);        }        catch (Exception e) {            throw new RuntimeException(                "Exception thrown in onCreate() of "                + data.instrumentationName + ": " + e.toString(), e);        }        try {            //调用Application的onCreate函数,做一些初始工作            mInstrumentation.callApplicationOnCreate(app);        } catch (Exception e) {            if (!mInstrumentation.onException(app, e)) {                throw new RuntimeException(                    "Unable to create application " + app.getClass().getName()                    + ": " + e.toString(), e);            }        }    } finally {        StrictMode.setThreadPolicy(savedPolicy);    }}
由以上代码可知,bindApplication函数将设置一些初始化参数,其中最重要的有:·  创建一个Application对象,该对象是本进程中运行的第一个Application。·  如果该Application有ContentProvider,则应安装它们。提示从以上代码可知,ContentProvider的创建就在bindApplication函数中,其时机早于其他组件的创建。·  在应用进程启动后,需要尽快调用AMS的attachApplication函数,该函数是这个刚呱呱坠地的应用进程第一次和AMS交互。此时的它还默默“无名”,连一个确定的进程名都没有。不过没关系,attachApplication函数将根据创建该应用进程之前所保存的ProcessRecord为其准备一切“手续”。·  attachApplication准备好一切后,将调用应用进程的bindApplication函数,在该函数内部将发消息给主线程,最终该消息由handleBindApplication处理。handleBindApplication将为该进程设置进程名,初始化一些策略和参数信息等。另外,它还创建一个Application对象。同时,如果该Application声明了ContentProvider,还需要为该进程安装ContentProvider。提示这个流程有点类似生孩子,一般生之前需要到医院去登记,生完后又需去注册户口,如此这般,这个孩子才会在社会有合法的身份。

boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
boolean didSomething = false;
final String processName = app.processName;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; –stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
if (!isFrontStack(stack)) {//不是焦点stack
continue;
}//找到焦点stack
ActivityRecord hr = stack.topRunningActivityLocked(null);
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (headless) {
Slog.e(TAG, “Starting activities not supported on headless device: ”
+ hr);
} else if (realStartActivityLocked(hr, app, true, true)) {
//通知该进程中的启动目标Activity
didSomething = true;
}
} catch (Exception e) {
Slog.w(TAG, “Exception in new application when starting activity ”
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0);
}
return didSomething;
}

“`

0 0
原创粉丝点击