Android应用的启动流程

  这里以在launcher中点击一个应用图标来启动一个新的android应用为例进行跟踪。
  启动过程比较复杂,先不管实际的代码实现,仅从最简单流程来考虑就需要实现以下步骤:
 1、找到当前的处于resume的activity先将它pause
2、创建一个新的activity
3、将新的activity置为resume
4、由于关系到多个activity的关系,所以需要有一个统一的服务进行管理,这个服务就是ActivityManagerService。
5、找到或者创建一个进程,让这个应用能够在上面运行。

我们来看android是怎样处理这些事务的:
Activity类:
Activity.startActivity(Intent intent)
调用了
Activity.startActivity(Intent intent, Bundle options):

public void startActivity(Intent intent, Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

参数options为null,所以调用Activity.startActivityForResult(Intent intent, int requestCode):

    public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            ...
        } else {
            ...
        }
    }

这里mParent为null,所以调用Instrumentation.execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options)
这里的mMainThread指的是调用者所在的ActivityThread(如果是在Launcher中点击图标的方式,则指的是launcher的主线程)。在大部分的时候ActivityThread我都视为Activity的代表。

然后调用了ActivityManagerNative.startActivity,这里实际上就是一个远程通信的过程了。
最终调用到
ActivityManagerService.startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options)

调用了ActivityManagerService.startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId)

调用到ActivityStackSupervisor.startActivityMayWait:

   final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
            Bundle options, int userId) {
       ...
        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                profileFile, profileFd, userId);
....

这里先调用resolveActivity通过PackageManager获得Activity相应的信息。
接着调用ActivityStackSupervisor.startActivityLocked

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
            String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
            boolean componentSpecified, ActivityRecord[] outActivity) {
            ...
                    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration,
                resultRecord, resultWho, requestCode, componentSpecified, this);
            ...

先是为新的activity创建了对应的ActivityRecord对象,这个对象将做为代表出现。
ActivityRecord类是这样的:
ActivityRecord( ActivityManagerService _service,
ProcessRecord _caller, //调用者的进程,与aInfo一起来决定当前Activity的应用包名
int _launchedFromUid, //启动Activity的Uid
String _launchedFromPackage, //启动Activity的包名
Intent _intent, //启动的Intent
String _resolvedType, //调用的包名
ActivityInfo aInfo, //Activity的信息
Configuration _configuration, //Activity的配置信息
ActivityRecord _resultTo, //parent Activity的信息
String _resultWho, //parent Activity的包名
int _reqCode, //startActivityForResult中的RequestCode
boolean _componentSpecified, //boolean componentSpecified = intent.getComponent() != null;
ActivityStackSupervisor supervisor,
ActivityContainer container, //大多数为null,一些特殊的启动方式会有值.
Bundle options)

...
err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
...

接着调用ActivityStackSupervisor.startActivityUncheckedLocked

    final int startActivityUncheckedLocked(ActivityRecord r,
            ActivityRecord sourceRecord, int startFlags, boolean doResume,
            Bundle options) {
            ...
 if (r.resultTo == null && !addingToTask
                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            targetStack = adjustStackFocus(r);//得到当前focus的stack
            moveHomeStack(targetStack.isHomeStack());
            if (reuseTask == null) {
                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                        newTaskInfo != null ? newTaskInfo : r.info,
                        newTaskIntent != null ? newTaskIntent : intent,
                        true), null, true);//创建一个新的TaskRecord
            } else {
                r.setTask(reuseTask, reuseTask, true);
            }
            newTask = true;

...

这里创建了一个TaskRecord实例,并将这个TaskRecord和我们为新的activity创建的ActivityRecord联系了起来。

    TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, boolean toTop) {
        TaskRecord task = new TaskRecord(taskId, info, intent);
        addTask(task, toTop);
        return task;
    }

TaskRecord是Task的代表,在android中Task的大致是任务的意思。显然一个Task中可以有多个activity。

    /** List of all activities in the task arranged in history order */
    final ArrayList<ActivityRecord> mActivities = new ArrayList<ActivityRecord>();

    /** Current stack */
    ActivityStack stack;

它里面维护了一个activity的列表。
addTask(task, toTop);会把这个新建的TaskRecord放入ActivityStack的ArrayList mTaskHistory中,将这个task放入ArrayList mTaskHistory的末端,这里是把mTaskHistory当栈来使用的,所以也就是放在栈顶。

...
targetStack.mLastPausedActivity = null;
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        mService.setFocusedActivityLocked(r);//设置当前activity为focused的acitity
        return ActivityManager.START_SUCCESS;
}

这里的mService就是ams。
接着调用了ActivityStack.startActivityLocked

    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) {
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            insertTaskAtTop(rTask);
            mWindowManager.moveTaskToTop(taskId);
        }
        //以上代码:如果是新的任务,将这个task放入ArrayList<TaskRecord> mTaskHistory的末端,这里是把mTaskHistory当栈来使用的。
        task = r.task;
...
        task.addActivityToTop(r);
...
//以上代码:把新的activity放入ArrayList<ActivityRecord> mActivities 的末端,这里把mActivities当栈来使用,所以视为放入栈顶。
        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked();
        }
...

到这里activity被添加到task的mActivities了。
然后又调用到ActivityStackSupervisor.resumeTopActivitiesLocked() {
return resumeTopActivitiesLocked(null, null, null);
}
接着调用ActivityStackSupervisor.resumeTopActivitiesLocked

    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = getFocusedStack();
        }
        boolean result = false;
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            if (isFrontStack(stack)) {
                if (stack == targetStack) {
                    result = stack.resumeTopActivityLocked(target, targetOptions);
                } else {
                    stack.resumeTopActivityLocked(null);//走这里
                }
            }
        }
        return result;
    }

调用ActivityStack.resumeTopActivityLocked(ActivityRecord prev)->
调用ActivityStack.resumeTopActivityLocked(ActivityRecord prev, Bundle options)

    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
    ...
    ActivityRecord next = topRunningActivityLocked(null);//这个就是我们要launch的activity
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

        if (next == null) {
           ...
            return mStackSupervisor.resumeHomeActivity(prev);//为空的话,就显示前一个
        }

        next.delayedResume = false;

        // If the top activity is the resumed one, nothing to do.
        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                    mStackSupervisor.allResumedActivitiesComplete()) {
           ...//如果当前的activity与将要launch的是同一个,就直接返回了
        }
...
 boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
        if (mResumedActivity != null) {
            pausing = true;
            startPausingLocked(userLeaving, false);
            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
        }
//然后调用startPausingLocked让当前处onresume的activiy进入onpause状态
next.sleeping = false;
                mService.showAskCompatModeDialogLocked(next);
                next.app.pendingUiClean = true;
                next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward());

                mStackSupervisor.checkReadyForSleepLocked();
//最后用scheduleResumeActivity去调用activity的onresume函数
...

先跟踪pause前一个activity的路线,之后我们再回来接着跟踪新的activity的路线。
ActivityStack.startPausingLocked:

   final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
   ...
           if (prev.app != null && prev.app.thread != null) {
           ...
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags);
           ...
        } else {
           ...
        }

这里的prev.app.thread是一个IApplicationThread实例。
在ActivityThread.java中,ApplicationThread.schedulePauseActivity:

        public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges) {
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0),
                    configChanges);
        }

发消息给H,然后H.handleMessage中处理该消息:

       public void handleMessage(Message msg) {
            switch (msg.what) {
            ...
               case PAUSE_ACTIVITY:
                    handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
                    maybeSnapshot();
            ...

ActivityThread.handlePauseActivity:

final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState) {
        ActivityClientRecord r = mActivities.get(token);
        return r != null ? performPauseActivity(r, finished, saveState) : null;
    }

Binder引用token转换成ActivityRecord的远程接口ActivityClientRecord
performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState) :

   final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {
        ...
             ArrayList<OnActivityPausedListener> listeners;
        synchronized (mOnPauseListeners) {
            listeners = mOnPauseListeners.remove(r.activity);
        }
        int size = (listeners != null ? listeners.size() : 0);
        for (int i = 0; i < size; i++) {
            listeners.get(i).onPaused(r.activity);
        }
        ...

到这里,调用者的activity已经被pause了,还要接着要为新的activity做相关的工作。
接着上面的ActivityStack.resumeTopActivityLocked:

    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
    ...
    if (next.app != null && next.app.thread != null) {//不走这里
    ...
    } else {
    ...
    mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    ...

next就是我们新的activity,到这里时,新的activity仅创建了一个新的ActivityRecord,并且为其设置了对应的task,但是next.app进程并未设置,所以走else的线路
ActivityStackSupervisor.startSpecificActivityLocked:

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
        r.task.stack.setLaunchTime(r);
        if (app != null && app.thread != null) {
        ...
        }
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

显然,这是一个新的进程,并没有存在,所以getProcessRecordLocked会返回null.
接下来,需要创建一个进程来跑我们的应用了:
ActivityManagerService.startProcessLocked:

   final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        ProcessRecord app;
        ...
        if (app == null) {
            app = newProcessRecordLocked(info, processName, isolated);
           ...
            mProcessNames.put(processName, app.uid, app);
            if (isolated) {
                mIsolatedProcesses.put(app.uid, app);
            }
        } else {
            ...
        }

        startProcessLocked(app, hostingType, hostingNameStr);
        ...
    }

newProcessRecordLocked创建了一个新的ProcessRecord对象,这个对象是用来保存进程的信息的。
ActivityManagerService.startProcessLocked:

   private final void startProcessLocked(ProcessRecord app,
            String hostingType, String hostingNameStr) {
            ...
             Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, null);

 app.setPid(startResult.pid);
 ...
            }

到这里Process.start返回的新进程的ID与ProcessRecord联系在一起了。
接下来的调用顺序是这样的:
Process.start->Process.startViaZygote->Process.zygoteSendArgsAndGetResult:
调用Process.start接口来创建一个新的进程
通过socket连接服务端(Zygote),并发送命令和参数。
ZygoteInit.java中
ZygoteInit.main:

   public static void main(String argv[]) {
           ...
            registerZygoteSocket();
           ...
            preload();
           ...
            gc();
           ...
            runSelectLoop();
            closeServerSocket();
        ...
    }

注册了一个socket,然后调用runSelectLoop负责监听来自客户端的请求。
ZygoteInit.runSelectLoop:

    private static void runSelectLoop() throws MethodAndArgsCaller {
...
        while (true) {
            ...

            if (index < 0) {
                ...
            } else if (index == 0) {
              ...
            } else {
                boolean done;
                done = peers.get(index).runOnce();
...
            }
        }
    }

收到消息后,交给runOnce处理
ZygoteConnection.runOnce:

   boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
...
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName);
...
        try {
            if (pid == 0) {
...
                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
                return true;
            } else {
                // in parent...pid of < 0 means failure
...
                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
            }

Zygote.forkAndSpecialize最终会使用fork()来创建一个新的进程。
fork()这个函数是用当前进程的数据拷贝一份来创建一个子进程,这个函数一次调用会有两次返回。一次在调用进程(父进程)中返回,另一次是在子进程中返回。
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;

这里我们关注子进程,也就是android应用运行所在的进程。(父进程将结果返回后,要接着监听客户端的请求。)

Zygote.handleChildProc:

    private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
...
                if (parsedArgs.classpath != null) {
                    cloader = new PathClassLoader(parsedArgs.classpath,
                            ClassLoader.getSystemClassLoader());
                } else {
                    cloader = ClassLoader.getSystemClassLoader();
                }

                try {
                    ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
                } catch (RuntimeException ex) {
                  ...
                }
            }
        }
    }

第一个参数是android.app.ActivityThread,这里就是把这个类load进来,然后调用它的main函数。
这就是为什么我们前面说每一个应用程序都有一个ActivityThread实例来对应的原因
ActivityThread.main:

    public static void main(String[] args) {
...
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        AsyncTask.init();
...
        Looper.loop();
...
    }

创建一个ActivityThread,为主线程准备好消息循环。thread.attach(false);附加相关的数据,包括mInstrumentation、mActivityToken,mContentResolver,mResources等。

thread.attach要做的事情很多,以后再慢慢分析。

到这里,整个android应用启动基本上就完成了。

ActivityRecord -> 代表应用的主线程

ArrayList mStacks 进程栈

final ArrayList mLruProcesses 运行应用程序列表

ArrayList mTaskHistory

ProcessMap mProcessNames//记录所有的进程

SparseArray mIsolatedProcesses//所有的单独进程

ProcessRecord 进程信息

附:
https://yq.aliyun.com/articles/62489#1
http://blog.csdn.net/myarrow/article/details/14223493
http://blog.csdn.net/dongxianfei/article/details/52239028
http://www.cnblogs.com/franksunny/archive/2012/04/17/2453403.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值