安卓系統啟動流程解析
一直以來一直想有深入研究原始碼的想法,最近一段時間工作比較少,得以時間研究,有點心得就給大家分享,今天給大家帶來的是安卓系統最開始的
話不多說 首先放圖
下面來詳解這張圖
從系統的角度上來講,Android系統的啟動過程可以分為 bootloader 引導,裝載和啟動 linux核心 啟動Android系統
BootLoader
bootloader 相當於電腦上的Bios 他的主要作用就是初始化基本的硬體裝置,建立記憶體空間對映, 為裝載linux核心準備好執行環境,當linux核心載入完畢之後,bootloder就會從記憶體中清除
對於FastBoot和Recover估計好多童鞋都不理解,fastboot是Android設計的一套通過usb來更新手機分割槽的映像協議,不過大部分廠商都搞掉了 google的nexus 上應該有的
Recovery模式是Android特有的升級系統,通過這個可以進行手機恢復出廠設定,或執行OTA,補丁和韌體升級,實質是啟動了一個文字模式的Linux。
bootloader啟動後會向記憶體中裝載boot.img映象檔案,這個映象檔案存放的是linux核心和一個根檔案系統,linux核心進行初始化之後,裝載完檔案系統,就啟動了init程序
Init程序
init程序是Linux建立的第一個程序,init程序會解析linux的指令碼檔案init.rc,根據這個檔案的內容 init程序會裝載Android的檔案系統,建立系統目錄,初始化屬性系統,啟動Android系統的重要的守護程序等,如上圖,
下面簡單的介紹一個下init程序fork出的幾個重要的程序:
Zygote程序: 當init程序初始化結束的時候,會啟動Zygote程序,看上圖可以看出來 zygote程序扶著fork出應用程序,是所有程序的父程序,Zygote程序初始化的時候會建立Dalivik虛擬機器,預裝載系統的資原始檔和java類,所有從Zygote程序fork出的使用者程序將繼承和共享這些資源,不用浪費時間重新載入(看到這裡是不是感覺突然明白了什麼?)幹完這些之後,Zygote程序也將變為守護程序,負責響應啟動APK應用的啟動請求。
SystemServer程序:SystemServer程序是Zygote程序fork出的第一個程序,也是整個Android系統的核心程序,在SystemServer主要執行的是Binder服務,SystemServer首要啟動本地服務 SensorService 接著啟動 ActivityManagerService,WindowsManagerService,PackgeManagerService等在內的所有java服務。
MediaServer程序:也是由init程序啟動,他包含了一些多媒體相關的本地Binder服務,包括CameraService,AudioFilingerService ,和AudioPolicyService。
當SystemServer載入完所有Java服務後最後會呼叫ActivityManagerService的SystemReady()方法,
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Making services ready");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
try {
mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
}
Slog.i(TAG, "WebViewFactory preparation");
WebViewFactory.prepareWebViewInSystemServer();
try {
startSystemUi(context);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
try {
if (mountServiceF != null) mountServiceF.systemReady();
} catch (Throwable e) {
reportWtf("making Mount Service ready", e);
}
try {
if (networkScoreF != null) networkScoreF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Score Service ready", e);
}
try {
if (networkManagementF != null) networkManagementF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Managment Service ready", e);
}
try {
if (networkStatsF != null) networkStatsF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Stats Service ready", e);
}
try {
if (networkPolicyF != null) networkPolicyF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Policy Service ready", e);
}
try {
if (connectivityF != null) connectivityF.systemReady();
} catch (Throwable e) {
reportWtf("making Connectivity Service ready", e);
}
try {
if (audioServiceF != null) audioServiceF.systemReady();
} catch (Throwable e) {
reportWtf("Notifying AudioService running", e);
}
Watchdog.getInstance().start();
// It is now okay to let the various system services start their
// third party code...
mSystemServiceManager.startBootPhase(
SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
try {
if (wallpaperF != null) wallpaperF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying WallpaperService running", e);
}
try {
if (immF != null) immF.systemRunning(statusBarF);
} catch (Throwable e) {
reportWtf("Notifying InputMethodService running", e);
}
try {
if (locationF != null) locationF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying Location Service running", e);
}
try {
if (countryDetectorF != null) countryDetectorF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying CountryDetectorService running", e);
}
try {
if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying NetworkTimeService running", e);
}
try {
if (commonTimeMgmtServiceF != null) {
commonTimeMgmtServiceF.systemRunning();
}
} catch (Throwable e) {
reportWtf("Notifying CommonTimeManagementService running", e);
}
try {
if (textServiceManagerServiceF != null)
textServiceManagerServiceF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying TextServicesManagerService running", e);
}
try {
if (atlasF != null) atlasF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying AssetAtlasService running", e);
}
try {
// TODO(BT) Pass parameter to input manager
if (inputManagerF != null) inputManagerF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying InputManagerService running", e);
}
try {
if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying TelephonyRegistry running", e);
}
try {
if (mediaRouterF != null) mediaRouterF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying MediaRouterService running", e);
}
try {
if (mmsServiceF != null) mmsServiceF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying MmsService running", e);
}
}
});
從上面的註釋我們可以得出他是去開啟lancher 具體的程式碼在這裡
public void systemReady(final Runnable goingCallback) {
synchronized(this) {
if (mSystemReady) {
// If we're done calling all the receivers, run the next "boot phase" passed in
// by the SystemServer
if (goingCallback != null) {
goingCallback.run();
}
return;
}
// Make sure we have the current profile info, since it is needed for
// security checks.
updateCurrentProfileIdsLocked();
.................................... 此處省略大量程式碼
// Start up initial activity.
mBooting = true;
<strong><u><span style="color:#000066;background-color: rgb(204, 204, 204);">startHomeActivityLocked(mCurrentUserId, "systemReady");</span></u></strong>
try {
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
+ " data partition or your device will be unstable.");
mHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget();
}
} catch (RemoteException e) {
}
if (!Build.isFingerprintConsistent()) {
Slog.e(TAG, "Build fingerprint is not consistent, warning user");
mHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget();
}
long ident = Binder.clearCallingIdentity();
try {
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
}
}, 0, null, null,
INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed sending first user broadcasts", t);
} finally {
Binder.restoreCallingIdentity(ident);
}
mStackSupervisor.resumeTopActivitiesLocked();
sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
}
}
這個裡面最重要的就是標出的那一行,呼叫的方法是原始碼是在這裡
boolean startHomeActivityLocked(int userId, String reason) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don't try to start anything.
return false;
}
<strong style="background-color: rgb(192, 192, 192);"> Intent intent = getHomeIntent();</strong>
ActivityInfo aInfo =
resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mStackSupervisor.startHomeActivity(intent, aInfo, reason);
}
}
return true;
}
看到這裡大家明白了吧,這個getHomeIntent() 就是開啟launcher應用的Inent
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
其實在上一段程式碼中還要去PackageManager去取一下所有型別為ACTION_MAIN的intent 然後才開的Launcher。
大致的流程就這些,中間有些部分會再以後的博文裡接著分析,如果看到有什麼錯誤的地方,都可以在下面評論中說出。希望我們共同進步!
相關推薦
安卓系統啟動流程解析
一直以來一直想有深入研究原始碼的想法,最近一段時間工作比較少,得以時間研究,有點心得就給大家分享,今天給大家帶來的是安卓系統最開始的 話不多說 首先放圖 下面來詳解這張圖 從系統的角度上來講,Android系統的啟動過程可以分為 bootloader 引
安卓系統啟動之Zygote程序啟動過程
背景 安卓系統啟動時首先啟動init程序,而後init程序會建立zygote程序,zygote程序則會fork出來SystemServer程序。在安卓開發學習之SystemServer啟動過程一文中記錄了閱讀SystemServer啟動的過程,現在就記錄一下Zygote程序的啟動過程 &nb
Android系統啟動流程——解析init程序啟動過程
最近主要是在看android關機充電流程,對android啟動有些迷惑,結合網上部落格專家的文章,加一些自己的理解。 1.init簡介 init程序是Android系統中使用者空間的第一個程序,作為第一個程序,它被賦予了很多極其重要的工作職責,比如建立zygote(孵化器
完整版unity安卓發布流程(包括SDK有原生系統依賴關系的工程)
產品 應用 技術分享 之前 完整 mage http .so ger 要3個東西!NDS,SDK,JDK, NDK官網下載:https://developer.android.google.cn/ndk/downloads/index.html(註意系統是不是64位) JD
Android系統啟動流程(一)解析init進程啟動過程
option 寫入 android change failed miss 通知 target sna 前言 作為“Android框架層”這個大系列中的第一個系列,我們首先要了解的是Android系統啟動流程,在這個流程中會涉及到很多重要的知識點,這個系列我們就來一一講解它們
Android系統啟動流程(一)解析init程序啟動過程
前言 作為“Android框架層”這個大系列中的第一個系列,我們首先要了解的是Android系統啟動流程,在這個流程中會涉及到很多重要的知識點,這個系列我們就來一一講解它們,這一篇我們就來學習init程序。 1.init簡介 init程序是An
Android 8.0 系統啟動流程之init.rc解析與service流程(七)
1、概述 上一篇文章中我們介紹了一下init.rc檔案中的語法規則,而本文將分析如何解析rc檔案,並對rc檔案中的某一service啟動過程進行分析。 2、解析.rc檔案 之前我們在文件中看到.rc檔案主要有根目錄下的 /init.rc ,以及
Android系統啟動流程(二)解析Zygote程序啟動過程
前言 上一篇文章我們分析了init程序的啟動過程,啟動過程中主要做了三件事,其中一件就是建立了Zygote程序,那麼Zygote程序是什麼,它做了哪些事呢?這篇文章會給你這些問題的答案。 1.Zygote簡介 在Android系統中,DVM(D
Android系統啟動流程(三)解析SyetemServer程序啟動過程
相關文章 Android系統架構與系統原始碼目錄 Android系統啟動流程(一)解析init程序啟動過程 Android系統啟動流程(二)解析Zygote程序啟動過程 前言 上一篇我們學習了Zygote程序,並且知道Zygote程序啟動了SyetemServ
安卓ServiceManager啟動:徹底理解ServiceManager啟動流程,這一篇就夠了
基於Android 6.0的原始碼剖析, 本文詳細地講解了ServiceManager啟動流程 framework/native/cmds/servicemanager/ - service_manager.c - binder.c kernel/driv
Linux系統啟動流程
linux系統啟動流程Linux系統啟動流程Linux系統啟動流程圖1、加電自檢 上電自檢POST,主要負責檢測系統外圍關鍵設備(如:CPU、內存、顯卡、I/O、鍵盤鼠標等)是否正常, 自檢完成後從BIOS中設置的系統啟動順序來搜索用於啟動系統的驅動器2、grub引導(1)grub引導第一階段(stag
移動端使用rem同時適應安卓ios手機原理解析,移動端響應式開發
size screen bsp 應用 屏幕 來看 比例 忽略 基礎 rem單位大家可能已經很熟悉,rem是隨著html的字體大小來顯示代表寬度的方法,我們怎樣進行移動端響應式開發呢 瀏覽器默認的字體大小為16px 及1rem 等於 16px 如果我們想要使1rem等於 12
XML文件解析【安卓7】——SAX解析
try 讀取資源文件 結束 文件解析 簡單 put log 空間 img XML文件解析 XML解析:XML技術是Android平臺的應用基礎, Android提供了多種解析XML的方式:SAX解析、DOM解析、PULL解析 SA
安卓系統下的多線程斷點下載實現
exc 源代碼 app 內存卡 linear 移植 getc exists see 近期研究多線程下載,寫了個demo。整理下來,或許會對別人有幫助。 多線程下載的話一般開啟兩到三個線程吧。假設線程太多的話時間會浪費在線程的切換上,倒是浪費了大把的時間
安卓2.3 js解析問題 split()
return bsp ace cti 2.3 space 安卓 string arr 安卓2.3版本號解析錯誤,split和parseInt都會把09和08都解析成0,07下面解析沒有問題。解決的方法是直接取個位數。 function getYMD(yMd){
CentOS系統啟動流程
centos系統啟動流程CentOS系統啟動流程CentOS的啟動流程總體順序如下(以CentOS 6為例): POST --> BootSequence(BIOS) --> Bootloader --> kernel [-->ramfs] -->rootfs(ro) -->
linux系統啟動流程(CentOS5/6/7為例)
centos 系統一個操作系統要完整啟動起來需要哪些步驟呢?今天以CentOS為例探索一下linux的啟動流程;一、Linux系統的組成--kernel+rootfs(根文件系統)kernel: 內核,進行進程管理、內存管理、網絡管理、驅動程序、文件系統、安全功能等等rootfs: 根文件系統1.內核設計流派
系統啟動流程
地址空間 object 2.6 全局 關系 roo 管理 mod 關聯關系 將系統自檢(BIOS)需要用到的指令,映射進CPU可以查找的線性地址空間(ROM),用來檢查硬件是否正常。 內核空
CentOS 6 系統啟動流程
linux 系統啟動流程一、Linux系統簡介 ⒈ Linux組成: kernel+rootfs ①kernel主要功能: 進程管理、內存管理、網絡管理、驅動程序、文件系統、安全功能 ②rootfs:程序和glibc
修改 安卓工作室 啟動頁
默認 幫助 新的 技術 本地 class文件 啟動 init 軟件 韓夢飛沙 韓亞飛 [email protected] yue31313 han_meng_fei_sha 修改 漢化之後 應該是 :啟動一個新的 安卓工作室項目 打開一個存在的安卓