首頁>技術>

前言

對於Android開發,幹上幾年後,都要進階,或者直接轉行了。如果你還在幹Android,想要進階 對Framework的了解是必不可少的過程,下面就開始進入今天的主題吧。

我們知道,對於任何程式語言而言,入口一般都是main函式。

那Android的程式入口在哪呢? 他的main函式是怎麼啟動起來的呢?

可能熟悉Android的同學,知道一個應用程式的入口在ActivityThread中,那有個問題,ActivityThread中的main函式是何時被誰被呼叫的呢?

將從本文中找到以上答案,如果已經熟悉了此過程的同學,可以再溫習一下。

Android架構

Android 平臺的基礎是 Linux 核心。Android Runtime (ART/Dalvik) 依靠 Linux 核心來執行底層功能,例如執行緒和低層記憶體管理等。

而在Android Runtime之上就是我們經常接觸的Java API Framework層, 如下圖是Android的系統架構圖

今天的主題不是此架構圖的各個部分解釋,而是離應用層更近的Framework層啟動過程分析。

Android Framework概述

如果我們這裡拋開Android架構圖,那狹義的Framewrok主要包含那些內容呢?

按我的理解,可以分為三個部分 服務端,客戶端,和依賴Linux底層能力的驅動部分。

服務端

主要是ActivityManagerService(AMS), WindowManagerService(WMS),PackageM anerService(PMS)

AMS 主要用於管理所有應用程式的ActivityWMS 管理各個視窗,隱藏,顯示等PMS 用來管理跟蹤所有應用APK,安裝,解析,控制權限等.

還有用來處理觸控訊息的兩個類KeyInputQueue和InputDispatchThread,一個用來讀訊息,一個用來分發訊息.

客戶端

主要包括ActivityThread,Activity,DecodeView及父類View,PhoneWindow,ViewRootImpl及內部類W等

ActivityThread主要用來和AMS通訊的客戶端,Activity是我們編寫應用比較熟悉的類

依賴Linux底層能力的驅動

主要是SurfaceFlingger(SF)和Binder驅動

每一個視窗都對應一個Surface,SF驅動的作用就是把每一個Surface顯示到同一個螢幕上Binder 核心驅動的作用,就是為上面的服務端和客戶端(或者服務端和服務端之間),提供IPC通訊用的。

Zygote

系統中執行的第一個Dalvik虛擬機器程式叫做zygote,該名稱的意義是“一個卵”,,因為接下來的所有 Dalvik虛擬機器程序都是通過這個“卵” 孵化出來的。

zygote程序中包含兩個主要模組,分別如下:

Socket服務端。該 Socket服務端用於接收啟動新的Dalvik程序的命令。Framework共享類及共享資源。當zygote程序啟動後,會裝載一些共享的類及資源,其中共享類是在preload-classes檔案中被定義,共享資源是在preload-resources中被定義。因為zygote程序用於孵化出其他Dalvik程序,因此,這些類和資源裝載後,新的Dalvik程序就不需要再裝載這些類和資源了,這也就是所謂的共享。

zygote程序對應的具體程式是app_rocess,該程式存在於system/bin目錄下,啟動該程式的指令是 在 init.rc中進行配置的。

Zygote 有️兩個優秀的特點

每fork出的一個程序都是一個Dalvik虛擬機器,獨立的程序可以防止一個程式的崩潰導致所有程式都崩潰,這種虛擬機器類似Java虛擬機器,對於程式設計師來說,可以直接使用Java開發應用zygote程序預先會裝載共享類和共享資源,這些類及資源實際上就是SDK中定義的大部分類和資源。因此,當通過zygote孵化出新的程序後,新的APK程序只需要去裝載A PK 自身包含的類和資源即可,這就有效地解決了多個APK共享Framework資源的問題。

SystemServer

zygote孵化出的第一個Dalvik程序叫做SystemServer,SystemServer僅僅是該程序的別名,而該程序具體對應的程式依然是app_process,因為SystemServer是從app_process中孵化出來的。

SystemServer中建立了一個Socket客戶端,並有AmS負責管理該客戶端,之後所有的Dalvik程序都將通過該Socket客戶端間接被啟動。當需要啟動新的APK程序時,AmS中會通過該Socket客戶端向 zygote程序的Socket服務端傳送一個啟動命令,然 後 zygote會孵化出新的程序。 上面提到的服務端,AMS,PMS,WMS等都是在SystemServer中啟動的.

Android Framework 源頭

作業系統的一般啟動流程,分為三個步驟

開機通電後,載入bootloader程式作業系統核心初始化執行第一個應用程式

Android 系統是基於Linux 核心Kernel,前面Linux bootloader這裡不做介紹,直接介紹作業系統核心初始化,在這個時候,它會載入init.rc檔案.

init.rc檔案

在Android根目錄下面,可以直接找到init.rc

generic_x86:/ # lsacct bin cache config data dev init init.rc init.usb.rc lost+found mnt oem product sdcard sys ueventd.rc adb_keys bugreports charger d default.prop etc init.environ.rc init.usb.configfs.rc init.zygote32.rc metadata odm proc sbin storage system vendor 

開啟init.rc

generic_x86:/ # cat init.rc# ..... 省略其他 # Now we can start zygote for devices with file based encryptiontrigger zygote-start# It is recommended to put unnecessary data/ initialization from post-fs-data# to start-zygote in device's init.rc to unblock zygote start.on zygote-start  # A/B update verifier that marks a successful boot. exec_start update_verifier_nonencrypted start netd start zygote start zygote_secondaryon property:vold.decrypt=trigger_restart_framework stop surfaceflinger# 啟動SF start surfaceflinger  # ..... 省略其他 media(媒體) network(網路)等啟動

也就是在 init.rc時,啟動Android 核心。

app_process

Android 核心也是main方法開始,他的main方法在 frameworks/base/cmds/app_process/app_main.cpp下

int main(int argc, char* const argv[]){ ... //初始化AndroidRuntime AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));  bool zygote = false; bool startSystemServer = false; bool application = false; String8 niceName; String8 className; // 根據引數具體判斷啟動那個服務 ++i; // Skip unused "parent dir" argument. 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 (!className.isEmpty()) { args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i); }else{ .... //啟動SystemServer if (startSystemServer) { args.add(String8("start-system-server")); } } .... if (zygote) { //啟動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."); }}

在這個Main方法中,先初始化了AppRuntime,他的父類是AndroidRuntime。然後我們看到了啟動了Java類ZygoteInit。

那c++程式碼裡怎麼啟動Java類呢,我們繼續看 start方法

void AndroidRuntime::start(const char* className, const Vector& options, bool zygote){ ... //啟動Java虛擬機器 if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { return; } ... //找到Java 裡面的Main方法 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 { //執行Main方法 env->CallStaticVoidMethod(startClass, startMeth, strArray); } .... }

可以看到最後先建立了Java虛擬機器,呼叫了Java的main方法,是不是感覺有些熟悉感了。

ZygoteInit

上面介紹到,會啟動Java的ZygoteInit類,那他裡面幹了些什麼呢? 我們來看一下關鍵程式碼,還是從Main方法開始

//ZygoteInit.java public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); ZygoteHooks.startZygoteNoThreadCreation();  //建立socket zygoteServer.createZygoteSocket(socketName); Zygote.createBlastulaSocket(blastulaSocketName);  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(); }  //fork SystemServer程序 if (startSystemServer) { Runnable r = forkSystemServer(abiList, socketName, zygoteServer); // child (system_server) process. if (r != null) { r.run(); return; } } //等待Socket的接入 if (caller == null) { Log.i(TAG, "Accepting command socket connections"); // The select loop returns early in the child process after a fork and // loops forever in the zygote. caller = zygoteServer.runSelectLoop(abiList); }

註釋寫了大概Zygote 啟動裡面的初始化內容

建立Socket載入系統資源啟動SystemServerrunSelectLoop 等待socket接入,開始執行fork新的程序.SystemServer

下面繼續看SystemServer 啟動的過程,從Main方法開始

//SystemServer.java /** * The main entry point from zygote. */ public static void main(String[] args) { new SystemServer().run(); }

很簡單,建立一個自己的物件,並執行run方法,看一下run方法

private void run() { ... if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); }  VMRuntime.getRuntime().clearGrowthLimit(); // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper();  // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); try { traceBeginAndSlog("StartServices"); startBootstrapServices(); startCoreServices(); startOtherServices(); SystemServerInitThreadPool.shutdown(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } finally { traceEnd(); }  Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited");}

run方法裡面主要進行了設定手機時間,設定虛擬機器記憶體大小,建立訊息迴圈Looper,建立SystemServiceManager等,最主要的是啟動了各類服務,我們接著看一下startBootstrapServices ,startCoreServices,startOtherServices方法

private void startBootstrapServices() { Installer installer = mSystemServiceManager.startService(Installer.class); mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);  mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); ....}private void startCoreServices() { ... mSystemServiceManager.startService(BatteryService.class); ...} private void startOtherServices() { final Context context = mSystemContext; VibratorService vibrator = null; DynamicAndroidService dynamicAndroid = null; IStorageManager storageManager = null; NetworkManagementService networkManagement = null; IpSecService ipSecService = null; NetworkStatsService networkStats = null; NetworkPolicyManagerService networkPolicy = null; ConnectivityService connectivity = null; NsdService serviceDiscovery= null; WindowManagerService wm = null; SerialService serial = null; NetworkTimeUpdateService networkTimeUpdater = null; InputManagerService inputManager = null; TelephonyRegistry telephonyRegistry = null; ConsumerIrService consumerIr = null; MmsServiceBroker mmsService = null; HardwarePropertiesManagerService hardwarePropertiesService = null; ....}

在這些方法中啟動了,我們的核心服務,和常用服務。 程式碼中也可以看到AMS,PMS,WMS等相關服務.

Launcher啟動介紹

一般服務啟動完成後,就會想繼呼叫systemReady()方法。 在SysytemServer startOtherServices中看到一個監聽回撥

mActivityManagerService.systemReady(() -> { try { startSystemUi(context, windowManagerF); } catch (Throwable e) { reportWtf("starting System UI", e); } }}static final void startSystemUi(Context context, WindowManagerService windowManager) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.SYSTEM); windowManager.onSystemUiStarted();}

而Ams啟動完成後,顯示Launcher

//AMS.java public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { ... startHomeActivityLocked(currentUserId, "systemReady"); // mStackSupervisor.resumeFocusedStackTopActivityLocked(); ... 複製程式碼

其實到這裡大致流程就介紹完了,但是文章開始的ActivityThread的main方法是何時被呼叫的,還沒回答,這裡不詳細展開,簡略回答一些.

ActivityThread的main方法如何被呼叫的?

AMS是管理Activity的啟動結束等,檢視AMS程式碼,噹噹前啟動的APP沒有建立程序時,會最終呼叫到ZygoteProcess,然後向 Zygote傳送一個socket請求。

resumeTopActivityLocked -> startProcessLocked -> Process.start() -> ZygoteProcess.start() -> ZygoteProcess.startViaZygote() —> ZygoteProcess.zygoteSendArgsAndGetResult()

接下來,看一下大致程式碼

//AMS.javaprivate final boolean startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) { //這裡entryPoint為ActivityThread final String entryPoint = "android.app.ActivityThread"; return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); }
//ZygoteProcess.javaprivate Process.ProcessStartResult startViaZygote(final String processClass,... ){ ArrayList argsForZygote = new ArrayList(); argsForZygote.add("--runtime-args"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); argsForZygote.add("--runtime-flags=" + runtimeFlags); argsForZygote.add("--target-sdk-version=" + targetSdkVersion); if (startChildZygote) { argsForZygote.add("--start-child-zygote"); } argsForZygote.add(processClass); synchronized(mLock) { return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), useBlastulaPool, argsForZygote); }}//發起Socket請求,給Zygoteprivate static Process.ProcessStartResult zygoteSendArgsAndGetResult( ArrayList args,..){ blastulaSessionSocket = zygoteState.getBlastulaSessionSocket(); final BufferedWriter blastulaWriter = new BufferedWriter( new OutputStreamWriter(blastulaSessionSocket.getOutputStream()), Zygote.SOCKET_BUFFER_SIZE); final DataInputStream blastulaReader = new DataInputStream(blastulaSessionSocket.getInputStream()); blastulaWriter.write(msgStr); blastulaWriter.flush(); ...}

最終 Zygote收到請求呼叫ZygoteInit中zygoteinit方法

//ZygoteInit.java public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { if (RuntimeInit.DEBUG) { Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); } Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit"); RuntimeInit.redirectLogStreams(); RuntimeInit.commonInit(); ZygoteInit.nativeZygoteInit(); return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); }

在 RuntimeInit中findStaticMain,最後在ZygoteInit中執行最終返回的這個Runnable,達到呼叫main方法的目的.

在這裡我也分享一份自己收錄整理的Android學習PDF+架構視訊+面試文件+原始碼筆記,還有高階架構技術進階腦圖、Android開發面試專題資料,高階進階架構資料幫助大家學習提升進階,也節省大家在網上搜索資料的時間來學習,也可以分享給身邊好友一起學習

如果你有需要的話,可以點贊+評論+轉發,關注我,然後私信我【進階】我發給你

  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 實時風控引擎Radar