Android启动过程

 

一.android点击桌面App图标activity启动流程

1、点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
2、system_server进程接收到请求后,向zygote进程发送创建进程的请求;
3、Zygote进程fork出新的子进程,即App进程;
4、App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
5、system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
6、App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
7、主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。

到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法

二.Android启动过程

第一个阶段:系统启动

1.首先是Android系统启动

  这时候第一进程是zygote。zygote英文是受精卵意思。android系统的所有进程都是由zygote进程fork而来。zygote最先启动第一个进程是鼎鼎大名的SystemServer进程。这个进程包含常说三大神级系统服务,分别ActivityManagerService,WindowManagerService及PackegeManagerService。

2.紧接着是所在应用的进程启动

http://androidxref.com/6.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java

进程入口在ActivityThread类的main()方法。
      main方法做以下几件事:
      1.初始化我们的mainLopper和mainHander,这样UI线程消息机制就开启了。
      2.调用ActivityThread的attach()方法。
public static void main(String[] args) {
        //....
        //1)创建Looper和MessageQueue对象,用于处理主线程的消息
        Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread(); thread.attach(false);// 2)建立Binder通道(创建新线程) Looper.loop(); //消息循环运行 throw new RuntimeException("Main thread loop unexpectedly exited"); }

第二个阶段:app注册
3.ActivityThread的attach()方法  

ActivityThread的attach()会接着调用ActivityManagerNatvie(一个单例类,可以获取ActivityManagerService实例)的getDeafault()返回ActivityManagerService实例。接着调用ActivityManagerService.attachApplication(mAPPThread)方法。这个mAPPThread是ApplicationThread的实例。

ApplicationThread:
 ApplicationThread是ActivityThread的内部类,他是App和系统跨进程交互的入口,它的实现类在客户端进程。
SystemServer的AMS通过ApplicationThread的ActivityManagerNatvieget.Deafault()返回ActivityManagerService实例来和App进程通信,包括生命周期的回调。
ApplicationThread在App进程的实现类通过H这个handler和ActivityThread跨线程交互,完成生命周期的最终回调,
这些时间类型是诸如:LAUNCH_ACTIVITY和RESUME_ACTIVITY以及Servivce的生命周期也是H这个Handler处理的,这个叫做H的Handler是UI线程。

public final class ActivityThread {
final ApplicationThread mAppThread = new ApplicationThread();  
private void attach(boolean system) { sCurrentActivityThread = this; //true守护线程 false 用户线程 守护线程是为用户线程服务的,一般业务逻辑的处理都写在守护线程里面 mSystemThread = system; if (!system) { ...... //获取代表类ActivityManagerProxy实例 final IActivityManager mgr = ActivityManagerNative.getDefault(); try { //调用ActivityManagerProxy的attachApplication实施绑定,最终会调用远程类AMS的attachApplication完成绑定 mgr.attachApplication(mAppThread); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } ...... } else { ...... try { mInstrumentation = new Instrumentation(); ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo); mInitialApplication = context.mPackageInfo.makeApplication(true, null); //调用application onCreate函数 mInitialApplication.onCreate(); } catch (Exception e) { ...... } } ...... } private class ApplicationThread extends ApplicationThreadNative {            //... } private class H extends Handler { //... } //... }

4.ActivityManagerService.attachApplication(mAPPThread)方法

http://androidxref.com/6.0.0_r1/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            //调用native函数获取当前进程的Id
            int callingPid = Binder.getCallingPid();
            //重置当前线程的IPC的id
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
}
获得了正在Binder通信的客户端的当前线程的id,然后和ApplicationThread对象作为参数传入到AMS的attachApplicationLocked。  
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);//在整个启动进程的流程中在前面已经push进入
            }
        } else {
            app = null;
        }
        if (app == null) {
            ......
            return false;//为null的时候直接返回.
        }
        //正常第一次开启时此时还是null 
        if (app.thread != null) {
            handleAppDiedLocked(app, true, true);
        }
        ......
        final String processName = app.processName;
        ......
        // 用来时例化ProcessRecord的thread变量.它是一个IApplicationThread对象. 
        app.makeActive(thread, mProcessStats);//在这里实现的附着!
        app.curAdj = app.setAdj = -100;
        app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
        app.forcingToForeground = null;
        updateProcessForegroundLocked(app, false, false);
        app.hasShownUi = false;
        app.debugging = false;
        app.cached = false;
        app.killedByAm = false;
        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
        List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
        ......
        try {
            ......
            // 这是一个远程调用,但最终会调用ApplicationThread的bindApplication函数完成绑定过程
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            updateLruProcessLocked(app, false, null);
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            ......
            return false;
        }
       ......return true;
}

 thread是ApplicationThreadProxy的对象引用,它是代理对象,先调用ApplicationThreadProxy的bindApplication方法,

接着在这个方法中又调用ApplicationThreadNative的函数onTransact(),然后onTransact()中根据code找到对应的case,最终会调用ApplicationThread的bindApplication方法。

5.调用ApplicationThreadProxy的 mAPPThread.bindApplication(ProcessRecord等参数)

 public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
            if (services != null) {//初始化缓存
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }
            setCoreSettings(coreSettings);
            //保存Bind数据
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableBinderTracking = enableBinderTracking;
            data.trackAllocation = trackAllocation;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            //发送信息
            sendMessage(H.BIND_APPLICATION, data);
}

在这里,bindApplication方法通过向ActivityThread的消息队列发送BIND_APPLICATION消息

 case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

 消息的处理调用handleBindApplication方法,handleBindApplication方法比较重要的是会调用如下方法

private void handleBindApplication(AppBindData data) {
    mBoundApplication = data;
    Process.setArgV0(data.processName);//设置进程名
    ...
    //获取LoadedApk对象
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
    ...
    // 创建ContextImpl上下文
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    ...
    try {
        // 此处data.info是指LoadedApk, 通过反射创建目标应用Application对象
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        ...
        mInstrumentation.onCreate(data.instrumentationArgs);
        //回调onCreate 
        mInstrumentation.callApplicationOnCreate(app);
    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

 在执行完bindApplication()之后进入ActivityStackSupervisor.attachApplicationLocked(),这样我们整个应用进程已经启动起来了。开始activity的启动逻辑了。

6.ActivityStackSupervisor.attachApplicationLocked(ProcessRecord)方法

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    final String processName = app.processName;
    boolean didSomething = false;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = stacks.get(stackNdx);
            if (!isFocusedStack(stack)) {
                continue;
            }
            ActivityRecord hr = stack.topRunningActivityLocked();
            if (hr != null) {
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                        && processName.equals(hr.processName)) {
                    try {
                        if (realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
                    } ......
                }
            }
        }
    }
    if (!didSomething) {
        ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
    }
    return didSomething;
}

  这个类是一个AMS的一个栈管理类,里面存储着ActivityStack的集合。在这个方法,会遍历各个ActivityStack,找到前台栈,找到里面的TopActivity。然后比较传进来的ProcessRecord.processName和UID是否和topActivity对用的ActivityRecord里面的一致。如果一致,就调用ActivityStackSupervisor.realStartAcvitiyLocked(ProcessRecord,ActivityRecord)方法。

7.ActivityStackSupervisor.realStartAcvitiyLocked(ProcessRecord,ActivityRecord)方法

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig){
       //...
        app.forceProcessStateUpTo(mService.mTopProcessState);
        app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

       //...
    return true;
}

  这个方法会调用传过来的ApplicationThread实例的ScheduelLaunchActivity(包括ActivityRecord)方法,所以真正执行的是ActivityThread中的scheduleLaunchActivity

第三个阶段:启动第一个Activity

8.ApplicationThread.ScheduelLaunchActivity(包括ActivityRecord)方法

     public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
        updateProcessState(procState, false);
        ActivityClientRecord r = new ActivityClientRecord();
        //...
        updatePendingConfiguration(curConfig);

        sendMessage(H.LAUNCH_ACTIVITY, r);
    }

  这个方法是跨进程的,会把ActivityRecord同步到App进程的ActivityRecordClient数据结构,用来后面构造Application和Activity等。

9.发送给H一个H.LAUNCH_ACTIVITY的消息

 public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            } break;
            //...
     }

10.调用ActivityThread的HandleLaunchActivity()方法

ActivityThread接收到SystemServer进程的消息之后会通过其内部的Handler对象分发消息,经过一系列的分发之后调用了ActivityThread的handleLaunchActivity方法:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    //...
    // Initialize before creating the activity
    WindowManagerGlobal.initialize();
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
      }
      //...
}

接着调用PerformLaunchActivity()方法和HandleResumeActivtiy()方法。performLauncherActivity看名字应该就是执行Activity的启动操作了

PerformLaunchActivity做的事

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE);
    }
    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(mInitialApplication.getPackageManager());
        r.intent.setComponent(component);
    }
    if (r.activityInfo.targetActivity != null) {
        component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity);
    }
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    }
   //....
    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
       //...
        if (activity != null) {
            Context appContext = createBaseContextForActivity(r, activity);
            ......
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window);
            //...
            activity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            //...
            //生命周期onStart、onresume
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }
            //...
    return activity;
}

   1.这个方法主要是构造Application和通过mInstrumention.newActivity()构造Activity。

      2.调用Activity的attach(application的ContextImpl等信息)

      可以发现这里我们需要的Activity对象终于是创建出来了,然后在代码中其调用Instrumentation的callActivityOnCreate方法。

Activity的attach(application的ContextImpl等信息)

  这个方法会初始化一个Window,以后详细讲,人格视图都是附在一个window的docorView上,然后由WMS.addView显示。

HandleLaunchActivtiy

  这个方法会调用Actiity的resume()方法,并且在makrVisible()里面调用WMS.addView(window), 这个windows里面的docorView的contentView就是onCreate()里面。
setContentView(int layout)设置的contentView。

最后显示出来了

  注意关于WMS.addView(window),这个系统服务,我们下次再讲,里面有一个类RootViewImpl,这个类负责管理我们contentView视图树的逐级绘制。

posted on 2019-12-23 20:28  左手指月  阅读(1035)  评论(0编辑  收藏  举报