Android系統啟動過程分析

主要流程

簡化流程圖
init程序啟動過程
init程序是Android系統中使用者空間的第一個程序。程序號為1。
引入init程序
第一步
當電源按下時引導晶片程式碼從預定的地方(固化為 ROM 中)開始執行。載入載入程式 BootLoader 到 RAM 中執行。
第二步
BootLoader是在Android作業系統開始執行前的一個小程式,主要作用是把系統OS拉起來執行。
第三步
當核心完成系統設定後,在系統檔案中尋找 init.rc 檔案,並啟動init程序。
啟動init程序就會執行它的入口函式main,檔案路徑為: system/core/init/init.cpp
int main(int argc, char** argv) { ...... if (is_first_stage) { boot_clock::time_point start_time = boot_clock::now(); umask(0); //建立和掛載啟動所需要的檔案目錄 mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); #define MAKE_STR(x) __STRING(x) mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)); chmod("/proc/cmdline", 0440); gid_t groups[] = { AID_READPROC }; setgroups(arraysize(groups), groups); mount("sysfs", "/sys", "sysfs", 0, NULL); mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL); mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)); mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)); mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)); ...... } ...... //對屬性服務進行初始化 property_init(); ...... epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (epoll_fd == -1) { PLOG(ERROR) << "epoll_create1 failed"; exit(1); } //用於設定子程序訊號處理函式,如果子程序異常退出,init程序會呼叫該函 //數中設定的訊號處理函式進行處理。 signal_handler_init(); ...... //啟動屬性服務 start_property_service(); ...... if (bootscript.empty()) { //解析init.rc配置檔案 parser.ParseConfig("/init.rc"); parser.set_is_system_etc_init_loaded( parser.ParseConfig("/system/etc/init")); parser.set_is_vendor_etc_init_loaded( parser.ParseConfig("/vendor/etc/init")); parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init")); } ...... while (true) { ...... if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) { am.ExecuteOneCommand(); } if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) { //重啟死去的服務 restart_processes(); } ...... } return 0; }
從上述程式碼中可以看出,init程序主要做了三件事:
- 建立和掛載啟動所需的檔案目錄。
啟動掛載了 tmpfs、devpts、proc、sysfs和selinuxfs
共5種檔案系統,這些是系統執行時目錄,也就是說只有在系統執行的時候才會存在。
- 初始化和啟動屬性服務。
屬性服務類似Windows平臺上的登錄檔管理器,登錄檔中以key-value的形式來記錄使用者、軟體的一些使用資訊。即使系統或軟體重啟,也能夠根據之前登錄檔中的記錄,進行相應的初始化工作。
- 解析
init.rc
檔案,建立 Zygote 程序。
該檔案的路徑為: system/core/rootdir/init.rc
。它是一個非常重要的配置檔案,是由Android初始化語言編寫的指令碼。Android8.0對該檔案進行來拆分,每個服務對應一個rc檔案,啟動 Zygote 的指令碼在 init.zygoteXX.rc
中定義,代表多少位處理器。這裡以64位為例。
system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root group root readproc socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd onrestart restart wificond writepid /dev/cpuset/foreground/tasks
這裡我們只分析 zygote程序 的建立,所以只貼出了 init.rc
檔案中的 Serivice 型別的語句,省略了其他語句;這是由Android初始化語言編寫的。它的格式如下:
service <name> <pathname> [ <argument> ]*
//名字 執行程式路徑 傳遞引數
< option >
//修飾詞,影響什麼時候啟動,如何啟動service。
< option >
......
上面的程式碼的含義就是:通知 init程序 建立名為 zygote 的程序,這個程序的執行路徑為: /system/bin/app/_process64
,其後面的程式碼是傳遞給 app_process64
的引數。 class main
指的是 zygote 的 classname 為 main 。
init.rc
中的 Service 型別的語句有相應的類來進行解析, Service 語句採用ServiceParser來進行解析,該實現程式碼在 system/core/init/service.app
中,程式碼在這不再貼出,大概的解析過程就是:根據引數創建出 Service物件 ,然後根據選項域中的內容填充 Service物件 ,最後將該物件加入 vector 型別的 Service連結串列 中。
在 init.rc
中有如下程式碼:
...... on nonencrypted class_start main class_start late_start ......
class_start是Android初始化語言中的 Command 型別的語句,對應的函式為 do_class_start
, 含義就是啟動classname為main的Service。 ,從上述程式碼我們知道 zygote 的 classname
為 main。
do_class_start
函式是在 system/core/bin/builtins.cpp
中,程式碼如下:
static int do_class_start(const std::vector<std::string>& args) { ServiceManager::GetInstance(). ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); }); return 0; }
ForEachServiceInClass
函式會遍歷 Service連結串列 ,找到 classname
為 main 的 Zygote ,並執行 StartIfNotDisabled ()
函式。
StartIfNotDisabled ()
函式的程式碼是在 system/core/init/service.cpp
中定義的,程式碼如下:
bool Service::StartIfNotDisabled() { if (!(flags_ & SVC_DISABLED)) { return Start(); } else { flags_ |= SVC_DISABLED_START; } return true; }
如果 Service 沒有在其對應的 rc檔案
中設定 disabled選項 ,就會執行 Start()
函式, Zygote 對應的檔案沒有設定 disabled選項 。
Start()
函式: system/core/init/service.cpp
bool Service::Start() { flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START)); //如果已執行,直接返回 if (flags_ & SVC_RUNNING) { return false; } ...... struct stat sb; //判斷需要啟動的Service對應的執行檔案是否存在,存在才會執行。 if (stat(args_[0].c_str(), &sb) == -1) { PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'"; flags_ |= SVC_DISABLED; return false; } ...... pid_t pid = -1; if (namespace_flags_) { pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr); } else { //如果沒有啟動,呼叫fork函式建立子程序 pid = fork(); } if (pid == 0) { umask(077); ...... //呼叫execve函式,子程序就會被啟動 if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) { PLOG(ERROR) << "cannot execve('" << strs[0] << "')"; } _exit(127); } ...... return true; }
呼叫 execve 函式
,子程序就會被啟動,就是執行對應的 main函式
, Zygote 的執行路徑為: system/bin/app_process64
,對應的檔案為 app_main.cpp
。
frameworks/base/cmds/app_process/app_main.cpp
:
int main(int argc, char* const argv[]) { ...... while (i < argc) { const char* arg = argv[i++]; 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 (zygote) { 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."); } }
呼叫 runtime.start
函式就啟動了 Zygote程序 。
Zygote程序
在 Android系統 中, DVM和ART、應用程式程序以及執行系統的關鍵服務SystemServer程序都是有Zygote程序建立的,我們也稱它為孵化器。 它通過 fock(複製程序) 的形式來建立應用程式程序和SystemServer程序,由於Zygote程序在啟動的時候會建立DVM或者ART,因此通過 fock 而建立的應用程式程序和SystemServer程序可以在內部獲取一個DVM或者ART的例項副本(也就是說一個Android應用程式對應這一個DVM或者ART)。
Zygote程序都是通過 fock 自身來建立子程序的,這樣 Zygote程序以及子程序 都會進入 app_main.cpp
的 main函式 ,所以在上述程式碼中先區分來當前執行在哪個程序中。執行 Zygote程序 就會執行 AndroidRuntime.start函式
。
frameworks/base/core/jni/AndroidRuntime.cpp
程式碼如下:
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ...... JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; //啟動Java虛擬機器 if (startVm(&mJavaVM, &env, zygote) != 0) { return; } onVmCreated(env); //為JVM註冊JNI方法 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } ...... //從app_main傳過來的引數classname值為:“com.android.internal.os.ZygoteInit” classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); for (size_t i = 0; i < options.size(); ++i) { jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); assert(optionsStr != NULL); env->SetObjectArrayElement(strArray, i + 1, optionsStr); } //將classname的“.”替換成“/” char* slashClassName = toSlashClassName(className); //找到ZygoteInit jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); } else { //找到ZygoteInit的main函式 jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); } else { //通過JNI呼叫ZygoteInit的main函式 env->CallStaticVoidMethod(startClass, startMeth, strArray); #if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } ...... }
上述程式碼最後會呼叫 ZygoteInit 的 main方法
,該方法是由Java語言編寫的,當前的執行邏輯在 Native 中,這就需要通過 JNI 來呼叫 Java 。這樣 Zygote 就從 Native 層近入了 Java框架層 。
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
的 main方法 程式碼如下:
public static void main(String argv[]) { ...... try { ...... //建立一個Server端的socket,socketName = “zygote” //在這個socket上會等待AMS的請求 zygoteServer.registerServerSocket(socketName); if (!enableLazyPreload) { bootTimingsTraceLog.traceBegin("ZygotePreload"); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); //預載入類和資源 preload(bootTimingsTraceLog); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); bootTimingsTraceLog.traceEnd(); // ZygotePreload } else { Zygote.resetNicePriority(); } //啟動SystemServer程序 if (startSystemServer) { startSystemServer(abiList, socketName, zygoteServer); } //等待AMS請求,裡面是一個while(true)迴圈 zygoteServer.runSelectLoop(abiList); zygoteServer.closeServerSocket(); }...... }
該方法中主要做了4件事:
1.建立一個Server端的socket(LocalServerSocket)。
2.預載入類和資源。
3.啟動SystemServer程序。
4.等待AMS請求建立新的應用程式程序。
從上面的程式碼我們看出 Zygote程序 主要做了如下幾件事情:
- 1.建立Java虛擬機器併為Java虛擬機器註冊JNI方法。
- 2.通過JNI呼叫 ZygoteInit 的
main函式
進入 Zygote 的Java框架層。 - 3.通過
registerServerSocket 方法
建立服務端Socket,並通過runSelectLoop 方法
等待 AMS 的請求來建立新的應用程式程序。 - 4.啟動 SystemServer 程序。
SystemServer程序
SystemServer程序主要用於建立系統服務,AMS、WMS、PMS都是由它來建立的。從上面得知通過呼叫 ZygoteInit 的 startSystemServer 方法
來啟動 SystemServer程序 ,下面就看一下該方法的程式碼:
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller, RuntimeException { ...... //建立args陣列,該陣列用來儲存啟動SystemServer的啟動引數 String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); //建立一個子程序,也就是SystemServer程序 pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } //當前程式碼執行在子程序中,也就是SystemServer程序 if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } //SystemServer程序複製了Zygote程序的地址空間,因此也會得到Zygote建立的Socket。 //該Socket對SystemServer程序沒有用,所以要關閉。 zygoteServer.closeServerSocket(); //處理SystemServer程序 handleSystemServerProcess(parsedArgs); } return true; }
從上面程式碼可以看出, SystemServer程序 的使用者id和使用者組id被設定為1000,並且擁有1001~1010、1018、1021、1032、3001~3010的許可權;程序名字為 system_server
;啟動的類名為: com.android.server.SystemServer
。
創建出 SystemServer程序 之後就會在該程序呼叫 ZygoteInit.handleSystemServerProcess 方法
,下面看一下該方法的程式碼:
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws Zygote.MethodAndArgsCaller { ...... if (parsedArgs.invokeWith != null) { ...... } else { ClassLoader cl = null; if (systemServerClasspath != null) { //建立PathClassLoader cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion); Thread.currentThread().setContextClassLoader(cl); } //呼叫zygoteInit方法 ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); } } public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws Zygote.MethodAndArgsCaller { if (RuntimeInit.DEBUG) { Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); } Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit"); RuntimeInit.redirectLogStreams(); RuntimeInit.commonInit(); //啟動Binder執行緒池 ZygoteInit.nativeZygoteInit(); //執行SystemServer的main方法 RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); }
在 zygoteInit方法
中建立了 Binder 執行緒池,這樣 SystemServer程序 就可以使用 Binder 於其他程序進行通訊了。
建立 Binder 執行緒池後會呼叫 RuntimeInit.applicationInit方法
,下面就接著看下該方法的程式碼:
/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws Zygote.MethodAndArgsCaller { ...... // Remaining arguments are passed to the start class's static main invokeStaticMain(args.startClass, args.startArgs, classLoader); } private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws Zygote.MethodAndArgsCaller { Class<?> cl; try { //通過反射得到SystemServer類 cl = Class.forName(className, true, classLoader); }...... Method m; try { //找到SystemServer的main方法 m = cl.getMethod("main", new Class[] { String[].class }); }...... int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException( "Main method is not public and static on " + className); } /* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */ throw new Zygote.MethodAndArgsCaller(m, argv); }
通過反射得到 SystemServer ,className的值就是上面提到的 com.android.server.SystemServer
,然後再找到 main方法
,最後將 main方法
傳入 Zygote .MethodAndArgsCaller
異常中並丟擲該異常。捕獲該異常的程式碼在 ZygoteInit.main方法
中,該main方法會呼叫 SystemServer 的 main方法
。
那為什麼不直接在invokeStaticMain方法中呼叫呢?而是在異常捕獲中呼叫?
原因是異常處理會清楚所有設定過程中需要的堆疊幀,讓 SystemServer 的 main方法
看起來像是 SystemServer程序 的入口。(在 Zygote
啟動 SystemServer程序 之後, SystemServer程序 做了很多準備工作,這些工作都是在 main方法
呼叫之前做的。)
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
的 main方法 程式碼:
public static void main(String argv[]) { ...... try { ...... //捕獲MethodAndArgsCaller異常 } catch (Zygote.MethodAndArgsCaller caller) { caller.run(); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); zygoteServer.closeServerSocket(); throw ex; } }
在異常處理中直接呼叫 Zygote.MethodAndArgsCaller 的 run方法
,可以看出 MethodAndArgsCaller 是 Zygote 的靜態內部類。
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static class MethodAndArgsCaller extends Exception implements Runnable { ...... public MethodAndArgsCaller(Method method, String[] args) { mMethod = method; mArgs = args; } ...... public void run() { try { mMethod.invoke(null, new Object[] { mArgs }); }...... } }
此處的 mMethod
就是 SystemServer 的 main方法
。
這樣就進入了 SystemServer 的 main方法
:
/frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) { new SystemServer().run(); } private void run() { try { ...... //建立Looper Looper.prepareMainLooper(); //載入動態庫“libandroid_servers.so” System.loadLibrary("android_servers"); performPendingShutdown(); //建立系統的上下文Context createSystemContext(); // 建立SystemServiceManager mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); SystemServerInitThreadPool.get(); } finally { traceEnd();// InitBeforeStartServices } // Start services. try { traceBeginAndSlog("StartServices"); //啟動引導服務 startBootstrapServices(); //啟動核心服務 startCoreServices(); //啟動其他服務 startOtherServices(); SystemServerInitThreadPool.shutdown(); }...... }
通過上面可以看出系統服務分為三種:
1.引導服務。
2.核心服務。
3.其他服務。
private void startBootstrapServices() { ...... Installer installer = mSystemServiceManager.startService(Installer.class); ...... mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class); ...... //需要注意的是 ActivityManagerService.Lifecycle實現了SystemService mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); ...... mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); ...... //在該方法中會把ActivityManagerService新增到ServiceManager中 mActivityManagerService.setSystemProcess(); ...... } private void startCoreServices() { ...... mSystemServiceManager.startService(DropBoxManagerService.class); traceEnd(); ...... mSystemServiceManager.startService(BatteryService.class); ...... } private void startOtherServices() { ...... mSystemServiceManager.startService(KeyChainSystemService.class); ...... mSystemServiceManager.startService(TelecomLoaderService.class); ...... }
部分服務表:
引導服務 | 作用 |
---|---|
Installer | 系統安裝APK時的一個服務,啟動完成Installer服務之後才能啟動其他的服務 |
ActivityManagerService | 負責四大元件的啟動、切換和排程 |
PowerManagerService | 計算系統中和Power相關的計算,然後決策系統應該如何反應 |
LightsService | 管理和顯示背光LED |
DisplayManagerService | 用來管理所有顯示的裝置 |
UserManagerService | 多使用者模式管理 |
SensorService | 為系統提供各種感應器服務 |
PackageManagerService | 用來對APK進行安、解析、刪除、解除安裝等操作 |
...... | ..... |
核心服務 | |
DropBoxManagerService | 用於生成和管理系統執行時的一些日誌檔案 |
BatteryService | 管理電池相關的服務 |
UsageStatsService | 收集使用者使用每一個app的頻率、使用時長 |
WebViewUpdateService | WebView更新服務 |
其他服務 | |
CameraService | 攝像頭相關服務 |
AlarmManagerService | 全域性定時器管理服務 |
InputManagerService | 管理輸入事件 |
WindowManagerService | 視窗管理服務 |
VrManagerService | VR模式管理服務 |
BluetoothService | 藍芽管理服務 |
NotificationManagerService | 通知管理服務 |
DeviceStorageMonitorService | 儲存相關管理服務 |
LocationManagerService | 定位管理服務 |
AudioService | 音訊相關管理服務 |
...... | ...... |
我們從上面看出相關的服務一種是通過 SystemServiceManager 的 startService方法
來啟動的;另一種是直接呼叫服務的 main方法
,比如: PackageManagerService 。下面分別看一下這兩種方式的程式碼實現:
/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
public class SystemServiceManager { ...... private final ArrayList<SystemService> mServices = new ArrayList<SystemService>(); ...... //startService方法有幾個過載,最終都會呼叫該方法 public void startService(@NonNull final SystemService service) { //註冊服務 mServices.add(service); // Start it. long time = System.currentTimeMillis(); try { //呼叫服務自身的onStart方法 service.onStart(); }...... } } public abstract class SystemService { ...... }
先將服務新增到 mService 中,它是一個儲存 SystemService 型別的ArrayList,這樣就完成來該服務的註冊工作。然後呼叫服務自身的 onStart()方法
來啟動服務。由 SystemServiceManager 建立並啟動的服務,都是繼承了 SystemService ,但是並沒有實現 IBinder ,所以是不可以進行 Binder通訊的 ,也就是由它管理的服務是用於程序內部通訊的。
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public class PackageManagerService extends IPackageManager.Stub implements PackageSender { ...... public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { PackageManagerServiceCompilerMapping.checkProperties(); PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); m.enableSystemUserPackages(); //註冊 ServiceManager.addService("package", m); return m; } ...... }
建立物件後新增到 ServiceManager 中,它是用來管理系統中各種Service的,由它管理的服務都實現了 IBinder ,所以在 ServiceManager 中註冊的服務是用於程序間通訊的:用於系統 C/S 架構中的 Binder通訊機制 。客戶端要使用某個 Service ,需要先到 ServiceManager 中查詢 Service 的資訊,然後根據該資訊與 Service 所在的 Server程序 建立通訊,這樣客戶端就可以使用 Service 了。
從上面的程式碼我們看出 SystemServer程序 主要做了如下幾件事情:
- 1.啟動 Binder執行緒池 ,這樣就可以與其他程序進行通訊了。
- 2.建立 SystemServiceManager ,用於對系統其他服務進行建立、啟動和宣告週期管理。
- 3.啟動各種系統服務。
SystemServer程序是 Zygote程序 fork
的第一個程序。其中 WindowManagerService、ActivityManagerService、PackageManagerService 等重要的可以 binder通訊 的服務都執行在這個 SystemServer程序 。
Launcher啟動過程
系統啟動的最後一步就是啟動一個應用程式來顯示系統中已經安裝的應用程式,這個程式就叫做 Launcher 。它在啟動過程中會請求 PackagerMangerService 返回系統中已經安裝的應用程式資訊,並將這些資訊封裝成一個快捷圖示列表顯示在系統螢幕上。這樣使用者就可以通過點選快捷圖示來啟動相應的應用程式了。
在上面 SystemServer程序 分析過程中,我們知道 ActivityManagerService(簡稱:AMS) 是負責四大元件的啟動、切換和排程的。系統桌面本身也是一個 Activity ,所以 Launcher 的啟動是在 AMS 中進行的,啟動 Launcher 的入口是 AMS 的 systemReady方法
。該方法是在 SystemServer 的 startOtherServices方法
中被呼叫的,下面就看一下該方法的實現程式碼:
private void startOtherServices(){ ...... mActivityManagerService.systemReady(() -> { Slog.i(TAG, "Making services ready"); traceBeginAndSlog("StartActivityManagerReadyPhase"); mSystemServiceManager.startBootPhase( SystemService.PHASE_ACTIVITY_MANAGER_READY); traceEnd(); traceBeginAndSlog("StartObservingNativeCrashes"); try { mActivityManagerService.startObservingNativeCrashes(); } catch (Throwable e) { reportWtf("observing native crashes", e); } traceEnd(); ...... }
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) { ...... synchronized (this) { ...... mStackSupervisor.resumeFocusedStackTopActivityLocked(); mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId); ...... } }
該方法中呼叫了 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked()方法
。
/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (targetStack != null && isFocusedStack(targetStack)) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } ...... return false; }
ActivityStack是用來描述 Activity 堆疊的。
最後經過重重呼叫,最終會呼叫 AMS 的 startHomeActivityLocked方法
。
boolean startHomeActivityLocked(int userId, String reason) { //判斷系統的執行模式和mTopAction的值 if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopAction == null) { return false; } 獲取Luncher啟動所需要的Intent Intent intent = getHomeIntent(); ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId); if (aInfo != null) { intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); aInfo = new ActivityInfo(aInfo); aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId); ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true); if (app == null || app.instr == null) { intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid); final String myReason = reason + ":" + userId + ":" + resolvedUserId; //啟動Luncher mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason); } } else { Slog.wtf(TAG, "No home screen found for " + intent, new Throwable()); } return true; } 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; }
mFactoryTest代表系統執行模式,執行模式有三種: 非工廠模式、低階工廠模式和高階工廠模式 ; mTopAction 表示第一個被啟動 Activity 元件的 Action
,它的預設值為: Intent.ACTION_MAIN
。
在 getHomeIntent方法
中,如果 mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL(低階工廠模式)
, Category 的值為: Intent.CATEGORY_HOME
。也就是說如果系統執行模式不是低階工廠模式那麼:
action = Intent.ACTION_MAIN
category = Intent.CATEGORY_HOME
而服務這個描述的應用程式就是 Luncher ,因為 Luncher 的 AndroidManifest
檔案中的 intent-filter
匹配了這兩個值:
/packages/apps/Launcher3/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.launcher3"> <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21"/> ...... <application ...... <activity android:name="com.android.launcher3.Launcher" android:launchMode="singleTask" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan" android:screenOrientation="unspecified" android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" android:enabled="true"> <intent-filter> //匹配規則 <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.MONKEY"/> <category android:name="android.intent.category.LAUNCHER_APP" /> </intent-filter> </activity> ...... </application> </manifest>
Luncher完成啟動後,作為桌面它會顯示應用程式圖示。