一直以來一直想有深入研究源碼的想法,最近一段時間工作比較少,得以時間研究,有點心得就給大家分享,今天給大家帶來的是安卓系統最開始的
話不多說 首先放圖
下面來詳解這張圖
從系統的角度上來講,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。
大致的流程就這些,中間有些部分會再以後的博文裏接着分析,如果看到有什麼錯誤的地方,都可以在下面評論中說出。希望我們共同進步!