国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

深入理解Activity啟動流程(三)–Activity啟動的詳細流程1

2019-11-08 00:00:59
字體:
來源:轉載
供稿:網友

本系列博客將詳細闡述Activity的啟動流程,這些博客基于Cm 10.1源碼研究。

深入理解Activity啟動流程(一)--Activity啟動的概要流程深入理解Activity啟動流程(二)--Activity啟動相關類的類圖深入理解Activity啟動流程(三)--Activity啟動的詳細流程2深入理解Activity啟動流程(四)--Activity Task的調度算法

本篇博客將開始介紹Activity啟動的詳細流程,由于詳細啟動流程非常復雜,故此分成兩篇來介紹。

本篇主要介紹前半部分的啟動流程:

1. Activity調用ActivityManagerService啟動應用2. ActivityManagerService調用Zygote孵化應用進程3. Zygote孵化應用進程

下篇介紹后半部分的啟動流程:

4. 新進程啟動ActivityThread5. 應用進程綁定到ActivityManagerService6. ActivityThread的Handler處理啟動Activity的消息

1. Activity調用ActivityManagerService啟動應用

點擊圖片可看大圖

activity_amservice

在launcher應用程序里啟動應用時,點擊應用圖標后,launcher程序會調用startActivity啟動應用,傳遞的intent參數:

123
intent = new Intent(Intent.ACTION_MAIN);   intent.addCategory(Intent.CATEGORY_LAUNCHER);   intent.setComponent(className);

activity最終調用Instrumentation的execStartActivity來啟動應用:

12345678910111213141516
//Activity類public void startActivityForResult(Intent intent, int requestCode, Bundle options) { if (mParent == null) {Instrumentation.ActivityResult ar =                mInstrumentation.execStartActivity(                    this, mMainThread.getapplicationThread(), mToken, this,                    intent, requestCode, options);   if (ar != null) {                mMainThread.sendActivityResult(                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),                    ar.getResultData());   } //...    }else{  //... }    

Instrumentation調用ActivityManagerPRoxy對象的startActivity方法啟動Activity,而ActivityManagerProxy只是ActivityManagerService對象在應用進程的一個代理對象,ActivityManagerProxy最終調用ActivityManagerService的startActvity方法啟動Activity。

12345678910111213141516
//Instrumentation類public ActivityResult execStartActivity(          Context who, IBinder contextThread, IBinder token, Activity target,          Intent intent, int requestCode, Bundle options) {//... try{             //...   int result = ActivityManagerNative.getDefault()                .startActivity(whoThread, intent,                        intent.resolveTypeIfNeeded(who.getContentResolver()),                        token, target != null ? target.mEmbeddedID : null,                        requestCode, 0, null, null, options);   } catch (RemoteException e) {   }   //...   }                     

2. ActivityManagerService調用Zygote孵化應用進程

點擊圖片可看大圖

amservice_zygote

ActivityManagerProxy對象調用ActivityManagerService對象(運行在system_server進程)的startActivity方法以啟動應用,startActivity方法接下來調用startActivityAsUser方法以啟動應用。在startActivityAsUser方法里會調用ActivityStack的startActivityMayWait方法以啟動應用,startActivityMayWait方法里啟動應用時,需先根據intent在系統中找到合適的應用的activity,如果有多個activity可選擇,則會彈出ResolverActivity讓用戶選擇合適的應用。

1234567891011121314151617
//ActivityStack類final int startActivityMayWait(IApplicationThread caller, int callingUid,            Intent intent, String resolvedType, IBinder resultTo,            String resultWho, int requestCode, int startFlags, String profileFile,            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,            Bundle options, int userId) {//…//根據intent在系統中找到合適的應用的activity,如果有多個activity可選擇,//則會彈出ResolverActivity讓用戶選擇合適的應用。  ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,                profileFile, profileFd, userId);//…int res = startActivityLocked(caller, intent, resolvedType,                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,                    startFlags, options, componentSpecified, null);//…}

在startActivityLocked方法里,對傳過來的參數做一些校驗,然后創建ActivityRecord對象,再調用startActivityUncheckedLocked方法啟動Activity。

startActivityUncheckedLocked方法負責調度ActivityRecord和Task,理解該方法是理解Actvity啟動模式的關鍵。

startActivityUncheckedLocked方法調度task的算法非常復雜,和當前回退棧,要啟動的acitivity的啟動模式以及taskAffinity屬性,啟動activity時設置的intent的flag等諸多要素相關,intent的flag就有很多種情況,故此算法非常復雜,需要閱讀源碼并結合特定啟動情況才能理解。

后續會介紹startActivityUncheckedLocked方法的實現,并結合特定場景分析調度算法。

接下來調用startActivityLocked將ActivityRecord加入到回退棧里:

12345678
//ActivityStack類final int startActivityUncheckedLocked(ActivityRecord r,          ActivityRecord sourceRecord, int startFlags, boolean doResume,          Bundle options) {//...          startActivityLocked(r, newTask, doResume, keepCurTransition, options);//...}

在startActivityLocked里調用resumeTopActivityLocked顯示棧頂Activity:

12345678
//ActivityStack類private final void startActivityLocked(ActivityRecord r, boolean newTask,        boolean doResume, boolean keepCurTransition, Bundle options) { //...         if (doResume) {   resumeTopActivityLocked(null); }  }

resumeTopActivityLocked(null)會調用另一個resumeTopActivityLocked方法顯示棧頂的acitivity:

1234
//ActivityStack類final boolean resumeTopActivityLocked(ActivityRecord prev) {    return resumeTopActivityLocked(prev, null);}

因為應用還未啟動過,所以調用startSpecificActivityLocked啟動應用,執行邏輯如下:

1234567891011
//ActivityStack類final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {  //...  if (next.app != null && next.app.thread != null) {    //…  }else{    //…   startSpecificActivityLocked(next, true, true);  } //... }

在startSpecificActivityLocked里調用mService.startProcessLocked啟動應用:

123456789
//ActivityStack類private final void startSpecificActivityLocked(ActivityRecord r,            boolean andResume, boolean checkConfig) {   ProcessRecord app = mService.getProcessRecordLocked(r.processName,              r.info.applicationInfo.uid);   //...   mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,        "activity", r.intent.getComponent(), false, false);}        

在ActivityManagerService的startProcessLocked方法里:

123456789101112131415161718192021222324252627282930
//ActivityManagerService類final ProcessRecord startProcessLocked(String processName,          ApplicationInfo info, boolean knownToBeDead, int intentFlags,          String hostingType, ComponentName hostingName, boolean allowWhileBooting,          boolean isolated) { ProcessRecord app; if (!isolated) {     app = getProcessRecordLocked(processName, info.uid); } else {     //... } //... if (app == null) {    app = newProcessRecordLocked(null, info, processName, isolated);    if (app == null) {        Slog.w(TAG, "Failed making new process record for "                + processName + "/" + info.uid + " isolated=" + isolated);        return null;    }    mProcessNames.put(processName, app.uid, app);    if (isolated) {        mIsolatedProcesses.put(app.uid, app);    }  } else {   //.. } //... startProcessLocked(app, hostingType, hostingNameStr); //...} 

在startProcessLocked方法里:

1234567891011121314151617
//ActivityManagerService類private final void startProcessLocked(ProcessRecord app,        String hostingType, String hostingNameStr) {  //...  try {      //...      // Start the process.  It will either succeed and return a result containing  // the PID of the new process, or else throw a RuntimeException.  //Zygote孵化dalvik應用進程后,會執行android.app.ActivityThread類的main方法      Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",              app.processName, uid, uid, gids, debugFlags, mountExternal,              app.info.targetSdkVersion, app.info.seinfo, null);      //...      } catch (RuntimeException e) {      //...  }}

在Process類的start方法里:

123456789101112131415
//Process類public static final ProcessStartResult start(final String processClass,                              final String niceName,                              int uid, int gid, int[] gids,                              int debugFlags, int mountExternal,                              int targetSdkVersion,                              String seInfo,                              String[] zygoteArgs) { try{                                startViaZygote(processClass, niceName, uid, gid, gids,                    debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);  }catch (ZygoteStartFailedEx ex) {    //...  }                    }                    

在Process類的startViaZygote方法里,會計算啟動應用進程用的各個參數,然后再調用zygoteSendArgsAndGetResult方法將這些參數通過socket發送給zygote進程,zygote進程會孵化出新的dalvik應用進程,然后告訴ActivityManagerService新啟動的進程的pid。

3. Zygote孵化應用進程

點擊圖片可看大圖

zygote

zygote進程將ZygoteInit作為啟動類,會執行它的main方法,先注冊ZygoteSocket,然后調用runSelectLoop方法,runSelectLoop方法會調用方法在ZygoteSocket上監聽請求,如果別的進程通過ZygoteSocket請求孵化進程,則孵化進程。

runSelectLoop方法的主要代碼:

123456789101112131415161718192021222324252627282930
//ZygoteInit類private static void runSelectLoopMode() throws MethodAndArgsCaller {  //...  while (true) {     //...      try {          fdArray = fds.toArray(fdArray);          index = selectReadable(fdArray);      } catch (IOException ex) {          throw new RuntimeException("Error in select()", ex);      }      if (index < 0) {          throw new RuntimeException("Error in select()");      } else if (index == 0) {          //監聽客戶連接請求          ZygoteConnection newPeer = acceptCommandPeer();          peers.add(newPeer);          fds.add(newPeer.getFileDesciptor());      } else {         //若客戶發送孵化進程的請求過來,         //此時便需要調用ZygoteConnection的runOnce方法孵化進程          boolean done;          done = peers.get(index).runOnce();          if (done) {              peers.remove(index);              fds.remove(index);          }      }  }}  

在runOnce方法里調用Zygote.forkAndSpecialize方法孵化進程,如果返回值為0表示是在孵化出來的應用進程里,此時會調用handleChildProc進行一些處理,并使用異常機制進行逃逸,會直接逃逸至ZygoteInit的main方法。

12345678910111213141516171819202122232425
//ZygoteConnection類boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {  //...  try {  //...      pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,              parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,              parsedArgs.niceName);  }   //...  try {      if (pid == 0) {          // in child          IoUtils.closeQuietly(serverPipeFd);          serverPipeFd = null;          //handleChildProc是一個很重要的函數,在該函數里使用了異常進行逃逸          handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);          //...        } else {         //...       }  } finally {       //...  }}

3.1 Zygote.forkAndSpecialize

Zygote的forkAndSpecialize方法會調用nativeForkAndSpecialize方法孵化進程,nativeForkAndSpecialize是一個本地方法,它的實現在dalvik/vm/native/dalvik_system_Zygote.cpp里,在該cpp文件里與nativeForkAndSpecialize對應的C++方法是Dalvik_dalvik_system_Zygote_forkAndSpecialize,在該方法里會調用forkAndSpecializeCommon孵化進程,在forkAndSpecializeCommon方法里會調用fork系統調用創建進程,因為使用的是fork機制所以創建進程的效率比較高。

3.2 handleChildProc

handleChildProc方法主要代碼:

12345678910111213141516171819202122232425262728293031323334353637
//ZygoteConnection類private void handleChildProc(Arguments parsedArgs,            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)            throws ZygoteInit.MethodAndArgsCaller {  //...  if (parsedArgs.runtimeInit) {  //...  } else {      String className;      try {          //這里得到的classname實際是android.app.ActivityThread          className = parsedArgs.remainingArgs[0];      } catch (ArrayIndexOutOfBoundsException ex) {          logAndPrintError(newStderr,                  "Missing required class name argument", null);          return;      }      //...      if (parsedArgs.invokeWith != null) {      //...      } else {          ClassLoader cloader;          if (parsedArgs.classpath != null) {              cloader = new PathClassLoader(parsedArgs.classpath,                      ClassLoader.getSystemClassLoader());          } else {              cloader = ClassLoader.getSystemClassLoader();          }          //調用ZygoteInit.invokeStaticMain執行android.app.ActivityThread的main方法                  try {              ZygoteInit.invokeStaticMain(cloader, className, mainArgs);          } catch (RuntimeException ex) {              logAndPrintError(newStderr, "Error starting.", ex);          }      }  }}

ZygoteInit的invokeStaticMain方法并不會直接執行className的main方法,而是會構造一個 ZygoteInit.MethodAndArgsCaller異常,然后拋出來,通過異常機制會直接跳轉到ZygoteInit的main方法, ZygoteInit.MethodAndArgsCaller類實現了Runnable方法,在run方法里會執行要求執行的main方法,故此跳轉到ZygoteInit的main方法后,異常會被捕獲,然后執行方法caller.run(),這樣便會執行android.app.ActivityThread的main方法。

ZygoteInit的invokeStaticMain方法主要代碼:

12345678910111213
//ZygoteInit類static void invokeStaticMain(ClassLoader loader,        String className, String[] argv)        throws ZygoteInit.MethodAndArgsCaller {  //...          Method m;  try {      m = cl.getMethod("main", new Class[] { String[].class });  } catch(//...){  }  //...  throw new ZygoteInit.MethodAndArgsCaller(m, argv);}

ZygoteInit.MethodAndArgsCaller主要代碼:

123456789
public static class MethodAndArgsCaller extends Exception        implements Runnable {    //...    public void run() {        try {            mMethod.invoke(null, new Object[] { mArgs });        }//...    }}

ZygoteInit的main方法相關代碼:

12345678910
//ZygoteInit類public static void main(String argv[]) {  try {      //...  } catch (MethodAndArgsCaller caller) {      caller.run();  } catch (RuntimeException ex) {      //...  }}

下面博客將介紹Activity詳細啟動流程的后半部分。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 安徽省| 辉县市| 汕尾市| 宁晋县| 大荔县| 灵武市| 宁化县| 舟山市| 永泰县| 海林市| 宝丰县| 同仁县| 化州市| 大新县| 荣昌县| 朝阳区| 娄烦县| 舟山市| 保定市| 樟树市| 时尚| 苍溪县| 柘荣县| 新龙县| 乐清市| 宣威市| 冀州市| 孟州市| 慈利县| 丹棱县| 镇坪县| 汾西县| 崇礼县| 稻城县| 宁阳县| 九龙城区| 工布江达县| 呼玛县| 桂东县| 南华县| 梁河县|