#頭條創作挑戰賽#
本文從Framework層對 Init程序啟動,Zygote程序,SystemServer程序,Launcher程序四部分對安卓系統系統啟動流程的完整源碼分析。篇幅較長,請耐心閱讀!
後續文章逐漸深入Framework層,剖析源碼,關注小編,學習不迷路!
簡介
當Android手機從按下開機鍵時,螢幕點亮,到Launcher系統桌面的顯示,整個過程系統是怎麼啟動的?下面我們一起深入源碼來看一下。整體流程如下圖所示。
源碼分析
init程序啟動
1.BootROM
當按下電源開關鍵時,引導晶片程式會從預定義的地方開始執行,加載系統引導程式BootLoader到RAM,啟動執行。
2.BootLoader
初始化系統硬體資源,引導作業系統啟動。
3.idel程序
初始化程序管理,記憶體管理,加載Binder驅動,Display,Camera 驅動等相關工作。
4. init程序啟動
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程序建立一個子程序用來啟動該應用程式。
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");
systemserver啟動流程
進入SystemServer程序,SystemServer中主要處理以下工作:
1)建立目前線程的Looper。
2) 初始化android_servers靜态庫。
3)建立系統context。
4)初始化主線程子產品。
5)建立系統服務管理對象-SystemServiceManager。
6) 啟動線程池。
7) 啟動程式引導服務。
8) 啟動核心服務。
9) 啟動其他服務。
10) 主線程循環等待消息處理。
Launcher啟動流程
Launcher作為android系統啟動流程的最後一步。它是android系統的桌面程式,在android系統中具有重要作用。用來顯示系統已經安裝的應用程式。
作用如下:
- Launcher作為android系統的啟動程式,用于系統程式的啟動。
- Launcher作為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程序的啟動總結如下:
當Launcher程序啟動完成,系統桌面展示出已經安裝的應用程式圖示。至此整個Android系統啟動流程就結束了。
還不會的同學趕緊學起來吧,感謝您的閱讀,創造不易,如果您覺得本篇文章對您有幫助,請點選關注小編,您的支援就是小編創作的最大動力!
後續文章逐漸深入WMS,PMS等Framework層,剖析源碼,關注小編,學習不迷路!