天天看點

深入Framework層剖析Android系統啟動流程

#頭條創作挑戰賽#

本文從Framework層對 Init程序啟動,Zygote程序,SystemServer程序,Launcher程序四部分對安卓系統系統啟動流程的完整源碼分析。篇幅較長,請耐心閱讀!

後續文章逐漸深入Framework層,剖析源碼,關注小編,學習不迷路!

簡介

當Android手機從按下開機鍵時,螢幕點亮,到Launcher系統桌面的顯示,整個過程系統是怎麼啟動的?下面我們一起深入源碼來看一下。整體流程如下圖所示。

深入Framework層剖析Android系統啟動流程

源碼分析

init程序啟動

1.BootROM

當按下電源開關鍵時,引導晶片程式會從預定義的地方開始執行,加載系統引導程式BootLoader到RAM,啟動執行。

2.BootLoader

初始化系統硬體資源,引導作業系統啟動。

3.idel程序

初始化程序管理,記憶體管理,加載Binder驅動,Display,Camera 驅動等相關工作。

4. init程序啟動

深入Framework層剖析Android系統啟動流程

Main.main()

Android系統啟動時 通過Android.bp啟動Main.cpp的main函數。

int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
    __asan_set_error_report_callback(AsanReportCallback);
#endif
    // 設定程序優先級
    setpriority(PRIO_PROCESS, 0, -20);
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }

    if (argc > 1) {
        //根據不同的參數 執行不同的函數。
        if (!strcmp(argv[1], "subcontext")) {
            android::base::InitLogging(argv, &android::base::KernelLogger);
            const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();

            return SubcontextMain(argc, argv, &function_map);
        }
         //第二次執行 
        if (!strcmp(argv[1], "selinux_setup")) {
            return SetupSelinux(argv);
        }
        //最後執行到 SecondStageMain
        if (!strcmp(argv[1], "second_stage")) {
            return SecondStageMain(argc, argv);
        }
    }
    //firstStageMain中再次調用main.cpp,參數傳為selinux_setup,後續執行SetupSelinux
    return FirstStageMain(argc, argv);
           

Init.SecondStageMain

Main.cpp的main方法被反複執行,最後執行到init.cp的SecondStageMain方法。

int SecondStageMain(int argc, char** argv) {

    .............
    //初始化屬性服務
    PropertyInit();

    // Umount the debug ramdisk after property service has read the .prop files when it means to.
    if (load_debug_prop) {
        UmountDebugRamdisk();
    }

    // Mount extra filesystems required during second stage init
    MountExtraFilesystems();

    // 設定系統安全政策
    SelinuxSetupKernelLogging();
    SelabelInitialize();
    SelinuxRestoreContext();
    //定義epoll機制
    Epoll epoll;
    if (auto result = epoll.Open(); !result.ok()) {
        PLOG(FATAL) << result.error();
    }

    //解析init.rc檔案
    LoadBootScripts(am, sm);
   .......................
    while (true) {
        // 循環等待處理
        auto epoll_timeout = std::optional<std::chrono::milliseconds>{};

        auto shutdown_command = shutdown_state.CheckShutdown();
       .........................
     
    }

    return 0;
}

}  // namespace init
           

SecondStageMain方法中,init程序主要處理:

1)挂載檔案,設定系統安全政策。

2)開啟屬性服務,注冊到epoll中。

3)解析init.rc ,啟動Zygote程序。

Zygote程序啟動

當安卓系統啟動後,會建立一個init程序,是以的程序都是這個init程序fork出來的,包括Zygote程序,當系統要求啟動一個Android應用程式時,都會通過AMS通知Zygote程序建立一個子程序用來啟動該應用程式。

深入Framework層剖析Android系統啟動流程

1.App_main.cpp

Zygote程序啟動時會執行app_main.cpp的main函數。

int main(int argc, char* const argv[])
{
   .............
   //初始化AppRuntime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
   
    argc--;
    argv++;
   ...........................

    //是否是zygote程序
    bool zygote = false;
    //是否啟動systemServer程序
    bool startSystemServer = false;
    bool application = false;
    //程序名稱
    String8 niceName;
    String8 className;

    ++i; 
    while (i < argc) {
        const char* arg = argv[i++];
        //設定zygote啟動
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    .........................
    
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {
        //如果是zygote程序  執行AppRuntime.start
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}
           

2.AndroidRuntime.cpp

AppRuntime繼承于AndroidRuntime,執行AppRuntime的start方法就是執行AndroidRuntime中的start方法。className傳入的是 "com.android.internal.os.ZygoteInit"。

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
   
    static const String8 startSystemServer("start-system-server");
    //記錄目前zygote是否是fork出SystemServer程序
    bool primary_zygote = false;

    
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //啟動虛拟機
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    //如果沒有虛拟機則建立新的虛拟機
    onVmCreated(env);

    /*
     * 注冊系統jni方法
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ..................
    /*
     * 啟動虛拟機線程,執行ZygoteInit的main方法
     * className :com.android.internal.os.ZygoteInit
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            //執行jni方法 進入:com.android.internal.os.ZygoteInit的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
    }
    ....................
}           

3.ZygoteInit.java

AndroidRuntime.start方法中 通過jni調用java代碼,執行com.android.internal.os.ZygoteInit的main方法。

public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;
        //标記zygote程序啟動
        ZygoteHooks.startZygoteNoThreadCreation();
        ...............
        Runnable caller;
        try {
           ...................
            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }
       
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                //預加載資源
                preload(bootTimingsTraceLog);
            }
            //建立zygote服務
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            //通過zygote程序fork出SystemServer程序
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                if (r != null) {
                    //執行SystemServer的main方法
                    r.run();
                    return;
                } 
            }
            //開啟循環
           caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }
    }
           

ZygoteInit的main方法主要的作用是:

1).預加載系統資源。

2).建立zygote的socket服務。

3).通過Zygote程序fork出SystemServer程序。

4).執行SystemServer的main方法,啟動程序。

5).zygote進入循環等待狀态,接收AMS傳遞的消息。

Zygote作為程序孵化器,當需要啟動一個程式時,首先會通過AMS使用Socket發送消息到Zygote程序,Zygote通過fork函數建立需要啟動的程式程序。

SystemServer程序啟動

ZygoteInit通過forkSystemServer建立出SystemServer程序,然後調用SystemServer的run方法進行執行。SystemServer的main方法。

//通過zygote程序fork出SystemServer程序
 if (startSystemServer) {
     Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
        if (r != null) {
            //執行SystemServer的main方法
            r.run();
          return;
        } 
 }

                       

1.SystemServer.java

/**
     * 從Zygote程序進入SystemServer程序.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
private void run() {
        TimingsTraceAndSlog t = new TimingsTraceAndSlog();
        try {
            ............省略部分代碼..............
            //建立目前線程的Looper
            Looper.prepareMainLooper();
            Looper.getMainLooper().setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);

            SystemServiceRegistry.sEnableServiceNotFoundWtf = true;

            //初始化android_servers靜态庫
            System.loadLibrary("android_servers");
             ..................
            // 建立系統context.
            createSystemContext();

            // 初始化主線程子產品
            ActivityThread.initializeMainlineModules();

            // 建立系統服務管理對象-SystemServiceManager
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // 啟動線程池
            SystemServerInitThreadPool.start();
            ...........................
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t); //啟動程式引導服務
            startCoreServices(t); //啟動核心服務
            startOtherServices(t);//啟動其他服務
        } catch (Throwable ex) {
        } finally {
            t.traceEnd(); // StartServices
        }
         ................

        // 主線程循環等待消息處理.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
               
深入Framework層剖析Android系統啟動流程

systemserver啟動流程

進入SystemServer程序,SystemServer中主要處理以下工作:

1)建立目前線程的Looper。

2) 初始化android_servers靜态庫。

3)建立系統context。

4)初始化主線程子產品。

5)建立系統服務管理對象-SystemServiceManager。

6) 啟動線程池。

7) 啟動程式引導服務。

8) 啟動核心服務。

9) 啟動其他服務。

10) 主線程循環等待消息處理。

Launcher啟動流程

Launcher作為android系統啟動流程的最後一步。它是android系統的桌面程式,在android系統中具有重要作用。用來顯示系統已經安裝的應用程式。

作用如下:

  1. Launcher作為android系統的啟動程式,用于系統程式的啟動。
  2. Launcher作為android系統的桌面程式,用于管理和顯示已安裝的應用程式圖示及桌面其他元件。

啟動流程分析

深入Framework層剖析Android系統啟動流程

1.SystemServer.startOtherServices

SystemServer的main方法中startOtherServices()啟動了其他服務,startOtherServices()中就包括了應用程式Launcher的啟動。

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
       ..............................
        //通過AMS開始啟動初始應用程式Launcher
        mActivityManagerService.systemReady(() -> {
            Slog.i(TAG, "Making services ready");
            t.traceBegin("StartActivityManagerReadyPhase");
            mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
            t.traceEnd();
            t.traceBegin("StartObservingNativeCrashes");
            try {
                mActivityManagerService.startObservingNativeCrashes();
            } catch (Throwable e) {
                reportWtf("observing native crashes", e);
            }
            t.traceEnd();
            ..................
}           

2.ActivityManagerService.systemReady

在ActivityManagerService中調用systemReady進行系統準備啟動工作。

public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
        t.traceBegin("PhaseActivityManagerReady");
        mSystemServiceManager.preSystemReady();
   .....................
    
     t.traceBegin("resumeTopActivities");
            mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
            t.traceEnd();
   .....................
}           

systemReady中調用了ActivityTaskManagerService的resumeTopActivities方法,接着看這個resumeTopActivities方法做了哪些工作。

3.ActivityTaskManagerService.resumeTopActivities

@Override
        public void resumeTopActivities(boolean scheduleIdle) {
            synchronized (mGlobalLock) {
                //進入RootWindowContainer
                mRootWindowContainer.resumeFocusedStacksTopActivities();
                if (scheduleIdle) {
                    mStackSupervisor.scheduleIdle();
                }
            }
        }           

在ActivityTaskManagerService中調用RootWindowContainer的resumeFocusedStacksTopActivities方法。

4.RootWindowContainer.resumeFocusedStacksTopActivities

//第一次進入    
boolean resumeFocusedStacksTopActivities() {
        return resumeFocusedStacksTopActivities(null, null, null);
    }
   //入參都為null
    boolean resumeFocusedStacksTopActivities(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        if (!mStackSupervisor.readyToResume()) {
            return false;
        }
        .........................
            if (!resumedOnDisplay) {
                final ActivityStack focusedStack = display.getFocusedStack();
                if (focusedStack != null) {
                    result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
                } 
                //首次啟動Launcher,入參為null
                else if (targetStack == null) {
                    //啟動homeActivity
                    result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
                            display.getDefaultTaskDisplayArea());
                }
            }
    
        return result;
    }           

系統首次啟動時,調用resumeFocusedStacksTopActivities傳入的參數都為nul,然後通過if判斷targetStack==null為true,調用resumeHomeActivity方法進行homeActivity啟動。

5.RootWindowContainer.resumeHomeActivity

boolean resumeHomeActivity(ActivityRecord prev, String reason,
            TaskDisplayArea taskDisplayArea) {
        //服務是否已經啟動
        if (!mService.isBooting() && !mService.isBooted()) {
            return false;
        }

        .....
        //從任務棧中擷取HomeActivity
        final ActivityRecord r = taskDisplayArea.getHomeActivity();
        final String myReason = reason + " resumeHomeActivity";

        // 已經啟動過了
        if (r != null && !r.finishing) {
            r.moveFocusableActivityToTop(myReason);
            return resumeFocusedStacksTopActivities(r.getRootTask(), prev, null);
        }
        //首次啟動
        return startHomeOnTaskDisplayArea(mCurrentUser, myReason, taskDisplayArea,
                false /* allowInstrumenting */, false /* fromHomeKey */);
    }
           

在resumeHomeActivity方法中,判斷服務是已經初始化完成,通過ActivityRecord任務棧擷取HomeActivty,如果已經啟動過則直接從任務棧中恢複,否則啟動新的HomeActivity,這裡系統是首次啟動,進入startHomeOnTaskDisplayArea執行。

6.RootWindowContainer.startHomeOnTaskDisplayArea

boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
            boolean allowInstrumenting, boolean fromHomeKey) {
        // 建立顯示區域
        if (taskDisplayArea == null) {
            final ActivityStack stack = getTopDisplayFocusedStack();
            taskDisplayArea = stack != null ? stack.getDisplayArea()
                    : getDefaultTaskDisplayArea();
        }

        Intent homeIntent = null;
        ActivityInfo aInfo = null;
        if (taskDisplayArea == getDefaultTaskDisplayArea()) {
            //建立Intent
            homeIntent = mService.getHomeIntent();
            aInfo = resolveHomeActivity(userId, homeIntent);
        } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
            Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
            aInfo = info.first;
            homeIntent = info.second;
        }
        //更新Intent啟動資訊
        homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
        homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
        //啟動HomeActivity
        mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
                taskDisplayArea);
        return true;
    }
    //建立Intent
    Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }           

homeIntent.setComponent()設定需要啟動的包名和HomeActivity資訊homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK),配置設定新的任務棧。在getHomeIntent()中建立Intent,并将mTopAction和mTopdata作為參數傳入Intent中,其中 mTopAction 預設為 Intent.ACTION_MAIN,同時設定Gategory為Intent.CATEGORY_HOME。系統通過Intent的參數比對Launcher的AndroidManifest中的内容,啟動Launcher程序。

系統啟動流程

從Android系統按下電源鍵到Launcher程序的啟動總結如下:

深入Framework層剖析Android系統啟動流程

當Launcher程序啟動完成,系統桌面展示出已經安裝的應用程式圖示。至此整個Android系統啟動流程就結束了。

還不會的同學趕緊學起來吧,感謝您的閱讀,創造不易,如果您覺得本篇文章對您有幫助,請點選關注小編,您的支援就是小編創作的最大動力!

後續文章逐漸深入WMS,PMS等Framework層,剖析源碼,關注小編,學習不迷路!

繼續閱讀