6.ActivityManagerService(四)App啟動流程AppThread 創(chuàng)建

所有代碼都是Android 11

整個Android 系統(tǒng)的SystemServer啟動流程,和app 啟動流程是非常類似的,只不過是參數(shù)不同,為了梳理整個的流程,下面我會從 zygote 的創(chuàng)建 加載 Vm 虛擬機開始分析整個流程

為了更好的讓 zygote fork 子進程 需要將每個進程的都需要的一些關于native 層的準備在SystemServer 進程創(chuàng)建錢就準備好,整個流程大致如下

1.初始化運行時環(huán)境 RunTime

2 初始化Vm ,

  1. 加載jni

4.調(diào)用 zygoteInit.java 離開 native 層 ,去到java 層

我是從app_main.cpp開始分析的, 從 開機的 init 進程 進入到 加載Android 環(huán)境,
在 app_main.cpp 的main 方法中,先創(chuàng)建了一個AppRunTime 對象

int main(int argc, char* const argv[])
{

  AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
   ///省略部分代碼.....
  while (i < argc) {
      const char* arg = argv[i++];
      if (strcmp(arg, "--zygote") == 0) {
          zygote = true;
          niceName = ZYGOTE_NICE_NAME;
      } 
  }

runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}

runtime.start 去到了 AndroidRunTime.cpp 中,在這里啟動了Vm ,注冊了jni ,然后離開了native層

創(chuàng)建jvm
  onVmCreated(env);

  注冊jni
  if (startReg(env) < 0) { 
      ALOGE("Unable to register all android natives\n");
      return;
  }
//離開native 層
CallStaticVoidMethod(startClass, startMeth, strArray);

離開了native 層就進入到了zygoteInint.java , 此時 zygote 已經(jīng)準備好了native 環(huán)境,看一下他的main 方法還做了哪些準備工作

初始化java 信息   
preload(bootTimingsTraceLog);

創(chuàng)建socket 服務器,為后續(xù)fork app 進程做準備
zygoteServer = new ZygoteServer(isPrimaryZygote);  

在這里可以看到他做了一個叫做preload 的方法,看一下都加載了什么

 static void preload(TimingsTraceLog bootTimingsTraceLog) {
     Log.d(TAG, "begin preload");
     bootTimingsTraceLog.traceBegin("BeginPreload");
     beginPreload();
     bootTimingsTraceLog.traceEnd(); // BeginPreload
     bootTimingsTraceLog.traceBegin("PreloadClasses");
     preloadClasses();// 加載系統(tǒng)類
     bootTimingsTraceLog.traceEnd(); // PreloadClasses
     bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders");
     cacheNonBootClasspathClassLoaders();// 沒讀明白這個是干什么的
     bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
     bootTimingsTraceLog.traceBegin("PreloadResources");
     preloadResources();// 加載系統(tǒng)資源
     bootTimingsTraceLog.traceEnd(); // PreloadResources
     Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
     nativePreloadAppProcessHALs();
     Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
     Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadGraphicsDriver");
     maybePreloadGraphicsDriver();//去了native 方法,
     Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
     preloadSharedLibraries();// 加載一些共享so庫,其實就三個:android、compiler_rt、jnigraphics
     preloadTextResources();// 加載字體資源
     // Ask the WebViewFactory to do any initialization that must run in the zygote process,
     // for memory sharing purposes.
     WebViewFactory.prepareWebViewInZygote();// 加載webview相關資源
     endPreload();
     warmUpJcaProviders();// 初始化JCA安全相關的參數(shù),干啥的還不清楚
     Log.d(TAG, "end preload");

     sPreloadComplete = true;
 }

初始化完資源并且建立了socket通道后,已經(jīng)為 fork 子進程做好了準備,下面就開始fork 子進程,forkSystemServer

Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

             // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
             // child (system_server) process.
             if (r != null) {
                 r.run();
                 return;
             }
caller = zygoteServer.runSelectLoop(abiList);

在這里也開啟一個looper ,等待fork其他子進程

接下來進入到Zygote 的 forkSystemServer 方法

 pid = Zygote.forkSystemServer(
                 parsedArgs.mUid, parsedArgs.mGid,
                 parsedArgs.mGids,
                 parsedArgs.mRuntimeFlags,
                 null,
                 parsedArgs.mPermittedCapabilities,
                 parsedArgs.mEffectiveCapabilities);

先說一下Zygote.forkSystemServer 也就是fork 進程的方法,這個方法比較有意思,一次調(diào)用他會返回兩個返回值, 如果這個返回值是-1 ,那么證明fork 子進程失敗, 如果返回的是0,那么說明回調(diào)的進程是子進程,如果返回的這個值大于0,回調(diào)的是fork進程

   if (pid == 0) { 
         if (hasSecondZygote(abiList)) {
             waitForSecondaryZygote(socketName);
         }

         zygoteServer.closeServerSocket();
         return handleSystemServerProcess(parsedArgs);
     }

這里面的判斷就是如果當前進程是子進程,那么將 handleSystemServerProcess(parsedArgs); 這個方法的返回值返回,繼續(xù)跟蹤

上面創(chuàng)建反射的方法的過程
m = cl.getMethod("main", new Class[] { String[].class });
static class MethodAndArgsCaller implements Runnable {
     /** method to call */
     private final Method mMethod;
     /** argument array */
     private final String[] mArgs;
     public MethodAndArgsCaller(Method method, String[] args) {
         mMethod = method;
         mArgs = args;
     }
     public void run() {
         try {
             mMethod.invoke(null, new Object[] { mArgs });
         } catch (IllegalAccessException ex) {
             throw new RuntimeException(ex);
         } catch (InvocationTargetException ex) {
             Throwable cause = ex.getCause();
             if (cause instanceof RuntimeException) {
                 throw (RuntimeException) cause;
             } else if (cause instanceof Error) {
                 throw (Error) cause;
             }
             throw new RuntimeException(ex);
         }
     }

跟蹤了好多層,最終返回是一個通過反射調(diào)用的 main 方法,那么在ZygoteInt mian 方法中 調(diào)用的 r.run() ,來反射到 SystemServer.main方法

我們在 Binder 的筆記中記錄了剩余的過程,下面我就在分析一下SystemServer 的啟動過程

SystemServer 的main 方法中new 了一個SystemServer ,并執(zhí)行了他的run 方法,在這個方法里面創(chuàng)建SystemServiceManager用來啟動 其他服務, 這個創(chuàng)建的過程大致分為了2種
1.該服務由于不需要binder 通信,那么創(chuàng)建的這個Service 則直接繼承自 SystemService ,被 SystemServiceManager 創(chuàng)建
2.該服務需要實現(xiàn)binder通信,那么他就需要繼承自對應的 IInterface.Stub ,實現(xiàn)服務端的代理,由于Java 的單繼承模式,SystemService 則創(chuàng)建了一個靜態(tài)內(nèi)部類,讓這個靜態(tài)內(nèi)部類在初始化的過程中創(chuàng)建該服務,

服務的啟動方式是通過反射獲取到服務,并將這個服務添加到SystemServiceManager 中 ,在啟動后會回調(diào)該服務的onStart 方法,這個里面又產(chǎn)生了不一致的地方
1.ActivityTaskManagerService 在他的onStart 方法中會將自身添加到 ServiceManager 中來統(tǒng)一管理,
2.ActivityManagerService 在onStart 方法中并沒有這么做,但是最后獲取 AMS 也是通過ServiceManager來獲取的,應該是在其他地方放進去的

創(chuàng)建完服務后,SystemServer 就開始進行Looper等待,

到了這里SystemServer 進程就初始化完畢了,比較有意思的是我在SystemServer 的run方法中發(fā)現(xiàn)他也為自己創(chuàng)建了 Context 上下文對象,我們來看看SystemServer 都干了什么

 private void createSystemContext() {
     ActivityThread activityThread = ActivityThread.systemMain();
     mSystemContext = activityThread.getSystemContext();
     mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

     final Context systemUiContext = activityThread.getSystemUiContext();
     systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
 }

 public static ActivityThread systemMain() {
     // The system process on low-memory devices do not get to use hardware
     // accelerated drawing, since this can add too much overhead to the
     // process.
     if (!ActivityManager.isHighEndGfx()) {
         ThreadedRenderer.disable(true);
     } else {
         ThreadedRenderer.enableForegroundTrimming();
     }
     ActivityThread thread = new ActivityThread();
     thread.attach(true, 0);
     return thread;
 }

在這里為SystemServer 也綁定了一個 ActivityThread ,這也驗證了開啟looper 的說法,如果不執(zhí)行l(wèi)ooper ,那么這個進程就會退出,整個系統(tǒng)就掛掉了

分析完了SystemServer 的啟動流程,再去分析app 的啟動流程就相對簡單一點

  1. Lanucher 通過binder 調(diào)用 AMS 啟動進程

2.AMS 通過 Socket 連接到 Zygote ,讓Zygote fork 進程 ,并在子進程中通過反射方法調(diào)用 ActivityThread .main

  1. ActivityThread main 方法 創(chuàng)建了 Looper ,并綁定了ActivityThread ,執(zhí)行 attach 方法 ,最后開啟循環(huán)
         Looper.prepareMainLooper();
         //之前SystemServer調(diào)用attach傳入的是true,這里到應用進程傳入false就行
         ActivityThread thread = new ActivityThread();
         thread.attach(false, startSeq);
         if (sMainThreadHandler == null) {
             sMainThreadHandler = thread.getHandler();
         }
         if (false) {
             Looper.myLooper().setMessageLogging(new
                     LogPrinter(Log.DEBUG, "ActivityThread"));
         }
         // End of event ActivityThreadMain.
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         //一直循環(huán),保障進程一直執(zhí)行,如果退出,說明程序關閉
         Looper.loop();
    

4.在ActivityThread attach 方法中調(diào)用 使用 ams 通過binder 調(diào)用 attachApplication ,同時也為ViewRootImpl 注冊了一個callback

//獲取AMS的本地代理類
         final IActivityManager mgr = ActivityManager.getService();
         try {
             //通過Binder調(diào)用AMS的attachApplication方法
             mgr.attachApplication(mAppThread, startSeq);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }

     ViewRootImpl.ConfigChangedCallback configChangedCallback
             = (Configuration globalConfig) -> {
         synchronized (mResourcesManager) {
             // TODO (b/135719017): Temporary log for debugging IME service.
             if (Build.IS_DEBUGGABLE && mHasImeComponent) {
                 Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, "
                         + "config=" + globalConfig);
             }

             // We need to apply this change to the resources immediately, because upon returning
             // the view hierarchy will be informed about it.
             if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
                     null /* compat */,
                     mInitialApplication.getResources().getDisplayAdjustments())) {
                 updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                         mResourcesManager.getConfiguration().getLocales());

                 // This actually changed the resources! Tell everyone about it.
                 if (mPendingConfiguration == null
                         || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                     mPendingConfiguration = globalConfig;
                     sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                 }
             }
         }
     };
     ViewRootImpl.addConfigCallback(configChangedCallback);

  1. AMS 啟動 application , app 啟動完成 ,至于 AMS是如何 調(diào)度的Applicaiton ,我會在后面詳細分析 AMS 的工作流程
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容