Android APP启动流程

预备知识

ServiceManager

通过init进程解析init.rc脚本构建,ServiceManager是Binder机制中的DNS服务器,负责将某Binder服务在ServiceManager注册时提供的ID到底层Binder驱动分配值的解析

是一个Linux程序,所属class为core。core组意味着这些进程会被同时启动或停止。有Zygote、media、surfaceflinger等

Zygote

通过init进程解析init.rc脚本构建,负责大部分应用进程和系统进程的创建。是Android系统的首个Java进程。

Zygote进程在App层中孵化出的第一个进程是Launcher进程,即手机的桌面APP。Zygote还会孵化出Browser、Email、Phone等APP进程,每个APP至少运行在一个进程上。所有APP进程都由Zygote进程fork生成。

nativeZygoteInit主导的本地系统服务启动

applicationInit负责的Java层系统服务启动(SystemServer)

SystemServer

提供系统服务,这些服务可以分为三类:BootStrap Services、Core Services、Other Services。

BootStrap Services:引导程序,代表系统服务中最核心的部分。这些Services依赖性强,需要统一启动。Android建议如果你的系统服务也有较强的依赖,可以添加到该服务中。启动的顺序大概是:Installer、AMS、电源管理、显示管理、包管理。

Core Services:优先级略低,包含LED和背光管理器,电池电量管理器,应用程序使用情况管理器等

Other Services:优先级最低,包含WMS等。

Android的C/S模式

在Android Framework中,四大组件的创建生命周期等是通过CS模式通信的

Server:指SystemServer,提供很多服务,如AMS、WMS、PMS

Client:指各个独立的APP进程。在开发过程中,我们可以通过包名和Activity类名来打开一个APP。然而startActivity背后的逻辑是这样的:先通过一系列调用发送请求给SystemServer的AMS,AMS接收到请求后,通知Zygote fork一个进程。APP中的Activity生命周期,都有AMS统一调度。这个过程涉及到3个进程:APP进程、SystemServer进程、Zygote进程。
APP进程与SystemServer进程通过Binder机制,进行跨进程通信。
SystemServer进程与Zygote进程通过Socket,进行跨进程通信。

Android Binder机制

在Android系统中,一个进程的空间,分为用户空间和内核空间两部分。进程内的用户空间和内核空间可以进行数据交互。进程间的用户空间是隔离开来的,只有内核空间能进行数据交互。
APP进程与SystemServer进程的交互,就是通过Binder机制进行跨进程通信(IPC),实现进程间的内核数据交互过程。Android专门设计了2个Binder接口,用作交互使用。

Looper

概括成一句话就是,Looper不断从MessageQueue中获取Message,然后交给Handler处理。

Looper对象的构造方法中,创建了消息队列对象,保存了当前线程信息。

Looper.prepare()为线程创建Looper。Looper.loop()开启消息循环,调用队列的阻塞方法next获取消息,为空则退出循环。

Handler

Handler 的sendMsg过程仅仅是向消息队列中插入了一条消息,MessageQueue 的 next 方法就会返回这条消息给 Looper,Looper 收到消息后就开始处理了,最终消息由Looper 交由Handler 处理,即 Handler 的 dispatchMessage 方法会被调用,这时Handler 就进入了处理消息的阶段。

ThreadLocal

线程内部存储类,通过它可以在指定线程中存储数据。日常开发中用到TL的很少,但是在Android源码中广泛使用。比如对于Handler,他需要获取当前线程Looper,这个时候通过TL就能轻松实现Looper在线程中的存取。

在不同线程中访问的同一个ThreadLocal对象,但是它们通过ThreadLocal获取到的值却是不一样的,这就是ThreadLocal的奇妙之处。

ThreadLocal之所以有这么奇妙的效果,是因为不同线程访问同一个ThreadLocal的get方法,ThreadLocal内部会从各自的线程中取出一个数组,然后再从数组中根据当前ThreadLocal的索引去查找出对应的value值。

Thread、Handler、Queue、Message的对应关系

一个Thread对应一个Looper。

一个Looper对应一个Queue。

一个Queue对应多个Handler。

一个Handler对应一个Queue。

场景一:在线程中使用Looper,没有创建handler,调用了Toast.makeText().show()。根据一个Handler对应一个Queue,查看Toast源码后可以发现,Toast使用了getLooper方法获取了当前线程了Looper,然后new Handler(looper),创建了Handler。之后sendMessage时,就会发送到该looper对应的Queue去。

场景二:在线程中使用Looper,创建了handler。那么根据一个Handler对应一个Queue,sendMessage时,就会发送到该looper对应的Queue去。

场景三:在主线程中使用了Toast.makeText().show()。根据一个Handler对应一个Queue,主线程在初始化时已经有了Looper。

ActivityStackSupervisor

活动栈的大管家,负责创建stack,创建task,移动task到stack,移动stack,启动activity等。

保存了各种状态的Activity的List。

UI层级

一个display包含多个stack

一个stack包含多个task

一个task包含多个activity

一个activity在wms中代表一个AppWindowToken,每个AppwindowToken上可能包含多个子Window,用WindowToken表示。

APP冷启动分析

1、启动APP进程: 当我们点击桌面程序的APP图标时,Launcher程序会调用Activity.startActivity()函数,通过Binder跨进程通信,发送消息给system_server进程。在system_server进程中,由AMS通过socket通信告知Zygote进程fork出一个子进程(APP进程)。

Instrumentation.ActivityResult ar =
    mInstrumentation.execStartActivity(
        this, mMainThread.getApplicationThread(), mToken, this,
        intent, requestCode, options);
private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        ···
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            ProcessStartResult startResult;
            if (hostingType.equals("webview_service")) {
                ···
            } else {
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, entryPointArgs);
            }
            ···
    }

2、开启APP主线程: APP进程启动后,会实例化一个ActivityThread,并执行其main函数,同时会创建ApplicationThread、Looper、Handler对象,开启主线程消息循环Looper.loop()。

3、创建并初始化Application和Activity: ActivityThread的main函数通过调用attach方法进行 Binder 通信,通知system_server进程执行AMS的attachApplication方法。在attachApplication方法中,AMS分别通过bindApplication、scheduleLaunchActivity方法,通知APP进程的主线程Handler,对APP进程的Application和Activity进行初始化,并执行Application、Activity的生命周期。

初始化Application

ActivityThread.attach()->IActivityManager.attachApplication(thread)->AMS.attachApplicationLocked(thread, callingPid)->IApplicationThread.bindApplication()->ActivityThread.sendMessage()->handleMessage()->ActivityThread.handleBindApplication()

->Application app = data.info.makeApplication(data.restrictedBackupMode, null);

->app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext);//创建Application对象

 mInstrumentation.callApplicationOnCreate(app)//执行Application生命周期

初始化Activity

ActivityThread.attach()->IActivityManager.attachApplication(thread)->AMS.attachApplicationLocked(mAppThread)->mStackSupervisor.attachApplicationLocked()->realStartActivityLocked->IApplicationThread.scheduleLaunchActivity()->ActivityThread.sendMessage()->ActivityThread.handleMessage()->ActivityThread.handleLaunchActivity()->ActivityThread.performLaunchActivity()

->activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent);//创建Activity对象

   activity.attach();

 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);执行Activity生命周期

//ActivityThread.java
public static void main(String[] args) {
        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);

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();//创建Looper
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }

        ActivityThread thread = new ActivityThread();
        thread.attach(false);//与AMS进行Binder通信,把线程信息发给AMS。

        AsyncTask.init();

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();//Looper循环

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
//ActivityThread.java
private void attach(boolean system) {
        ···
        if (!system) {
            ···
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ···
        } else {
           ···
        }
        ···
    }
//ActivityManagerService.java
@Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            ···
            attachApplicationLocked(thread, callingPid);
            ···
        }
    }

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        ···
        try {
            ···
            if (app.instr != null) {
                thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial);
            } else {
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial);
            }
            ···
        } catch (Exception e) {
            ···
        }
        ···
        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                ···
            }
        }
        ···
    }

4、UI布局和绘制: 主线程Handler初始化Activity时,会执行创建PhoneWindow、初始化DecorView的操作,并且添加布局到DecorView的ContentView中。ContentView,对应着Activity的setContentView中设置的layout.xml布局文件所在的最外层父布局。

 

posted @ 2022-07-06 11:43  Miraculous_B  阅读(1177)  评论(0)    收藏  举报