c++builder启动了怎么停止_App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析...
在我的上一篇文章:
AJie:按下電源鍵后竟然發生了這一幕 —— Android 系統啟動流程分析?zhuanlan.zhihu.com我們分析了系統在開機以后的一系列行為,其中最后一階段 AMS(ActivityManagerService) 會啟動 Launcher 來展示我們手機中所有已安裝的應用圖標,點擊圖標后相應的應用程序將會被系統啟動運行并展示在我們面前,那么,點擊了圖標之后系統道理做了哪些工作呢?應用進程是怎么被啟動的呢?Activity 的生命周期是什么時候被誰調用的呢?本文將繼續基于 Android Nougat 的 frameworks 層源碼的解答這些問題。
閱讀建議: 如果你是首次閱讀這個過程的源碼,建議你忽略一些細枝末節的代碼,先抓主干代碼,從整體上理解代碼的執行流程(右下角文章目錄視圖中可以點擊跳轉到相應章節),否則將會被細節的代碼擾亂思路。最后可以回頭多看幾遍,這時候如果有需要可以追蹤一些枝干代碼,做到融會貫通。
1. Launcher —— AMS
1.1 調用過程分析
1.1.1 Launcher.onClick
在 Launcher app 的主 Activity —— Launcher.java 中,App 圖標的點擊事件最終會回調 Launcher.java 中的 onClick 方法,
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java:
public void onClick(View v) {...Object tag = v.getTag();if (tag instanceof ShortcutInfo) {// 從快捷方式圖標啟動onClickAppShortcut(v);} else if (tag instanceof FolderInfo) {// 文件夾if (v instanceof FolderIcon) {onClickFolderIcon(v);}} else if (v == mAllAppsButton) {// “所有應用”按鈕onClickAllAppsButton(v);} else if (tag instanceof AppInfo) {// 從“所有應用”中啟動的應用startAppShortcutOrInfoActivity(v);} else if (tag instanceof LauncherAppWidgetInfo) {// 組件if (v instanceof PendingAppWidgetHostView) {onClickPendingWidget((PendingAppWidgetHostView) v);}} }1.1.2 Launcher.onClickAppShortcut
如果是快捷方式圖標,則調用 onClickAppShortcut 方法進而調用 startAppShortcutOrInfoActivity 方法:
@Thunk void startAppShortcutOrInfoActivity(View v) {Object tag = v.getTag();final ShortcutInfo shortcut;final Intent intent;if (tag instanceof ShortcutInfo) {shortcut = (ShortcutInfo) tag;// 去除對應的 Intent 對象intent = shortcut.intent;int[] pos = new int[2];v.getLocationOnScreen(pos);intent.setSourceBounds(new Rect(pos[0], pos[1],pos[0] + v.getWidth(), pos[1] + v.getHeight()));} else if (tag instanceof AppInfo) {shortcut = null;intent = ((AppInfo) tag).intent;} else {throw new IllegalArgumentException("Input must be a Shortcut or AppInfo");}// 調用 startActivitySafely 方法boolean success = startActivitySafely(v, intent, tag);mStats.recordLaunch(v, intent, shortcut);if (success && v instanceof BubbleTextView) {mWaitingForResume = (BubbleTextView) v;mWaitingForResume.setStayPressed(true);} }1.1.3 Launcher.startActivity
獲取相應 App 的 Intent 信息之后,調用 startActivity 方法:
private boolean startActivity(View v, Intent intent, Object tag) {// 啟動新的任務棧intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);try {...if (user == null || user.equals(UserHandleCompat.myUserHandle())) {StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();try { StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());// 調用 Activity 的 startActivity 方法startActivity(intent, optsBundle);} finally {StrictMode.setVmPolicy(oldPolicy);}} else {launcherApps.startActivityForProfile(intent.getComponent(), user,intent.getSourceBounds(), optsBundle);}return true;} catch (SecurityException e) { ...}return false; }1.1.4 Activity.startActivity
這里最終調用了 Activity 中的 startActivity 方法,并且設置 Flag 為 FLAG_ACTIVITY_NEW_TASK。到此為止,已經跟啟動普通的 Activity 流程匯合起來了,繼續往下分析。
frameworks/base/core/java/android/app/Activity.java:
@Override public void startActivity(Intent intent, @Nullable Bundle options) {// 第二個參數為 -1 表示不需要回調 onActivityResult 方法if (options != null) {startActivityForResult(intent, -1, options);} else {// Note we want to go through this call for compatibility with// applications that may have overridden the method.startActivityForResult(intent, -1);} }1.1.5 Activity.startActivityForResult
調用 Activity 的 startActivityForResult 方法
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {// mParent 是當前 Activity 的父類,此時條件成立if (mParent == null) {// 調用 Instrumentation 的 execStartActivity 方法Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this,mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);...} else {...} }1.1.6 Instrumentation.execStartActivity
frameworks/base/core/java/android/app/Instrumentation.java:
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {...try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess(who);// 獲取 AMS 的代理對象并調用其 startActivity 方法int result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null; }1.1.7 ActivityManagerProxy.startActivity
以上過程是在 Launcher App 所在的進程中發生的,在我的另外一篇文章
AJie:借助 AIDL 理解 Android Binder 機制——AIDL 的使用和原理分析?zhuanlan.zhihu.com中我們分析了 AIDL 的實現過程,由于遠程 Service 跟使用 Service 的 Activity 不在同一個進程中,因此他們之間交互需要通過 Binder IPC 機制的支持,在這個過程中Client 首先獲取到 Server 端的代理對象,在 Client 看來 Server 代理對象同樣具有 Server 本地對象承諾的能力,因此 Client 可以調用 Server 代理對象跟 Sever 本地對象進行數據交互,Binder 驅動作為橋梁在他們中間起到中間人的作用。
在Android 系統啟動流程分析中曾經分析過,AMS 是運行在 system_server 線程中的,這時 AMS 就相當于 AIDL 中的遠程 Service,App 進程要與 AMS 交互,需要通過 AMS 的代理對象 AMP(ActivityManagerProxy) 來完成,來看 ActivityManagerNative.getDefault() 拿到的是什么:
frameworks/base/core/java/android/app/ActivityManagerNative.java:
static public IActivityManager getDefault() {return gDefault.get(); }getDefault 是一個靜態變量:
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {protected IActivityManager create() {// 向 ServiceManager 查詢一個 key 為 "activity" 的引用IBinder b = ServiceManager.getService("activity");if (false) {Log.v("ActivityManager", "default service binder = " + b);}IActivityManager am = asInterface(b);if (false) {Log.v("ActivityManager", "default service = " + am);}return am;} };同樣,在文章
AJie:借助 AIDL 理解 Android Binder 機制——Binder 來龍去脈?zhuanlan.zhihu.com中也講到過:
ServiceManager 是 Binder IPC 通信過程的核心,是上下文的管理者,Binder 服務端必須先向 ServerManager 注冊才能夠為客戶端提供服務,Binder 客戶端在與服務端通信之前需要從 ServerManager 中查找并獲取 Binder 服務端的引用。這里通過 "activity" 這個名字向 ServiceManager 查詢 AMS 的引用,獲取 AMS 的引用后,調用 asInterface 方法:
static public IActivityManager asInterface(IBinder obj) {if (obj == null) {return null;}// 根據 descriptor 查詢 obj 是否為 Binder 本地對象,具體過程請看前文中提到的文章IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor);if (in != null) {return in;}// 如果 obj 不是 Binder 本地對象,則將其包裝成代理對象并返回return new ActivityManagerProxy(obj); }因為 AMS 與 Launcher App 不在同一個進程中,這里返回的 IBinder 對象是一個 Binder 代理對象,因此這類將其包裝成 AMP(ActivityManagerProxy) 對象并返回,AMP 是 AMN(ActivityManagerNative) 的內部類,查看 AMP 類 :
class ActivityManagerProxy implements IActivityManager {public ActivityManagerProxy(IBinder remote){mRemote = remote;}public IBinder asBinder(){return mRemote;}public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {...// 調用號為 START_ACTIVITY_TRANSACTIONmRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);reply.readException();int result = reply.readInt();reply.recycle();data.recycle();return result;}...public ComponentName startService(IApplicationThread caller, Intent service,String resolvedType, String callingPackage, int userId) throws RemoteException{...mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);reply.readException();ComponentName res = ComponentName.readFromParcel(reply);data.recycle();reply.recycle();return res;}... }可以看到,AMP 里面將客戶端的請求通過 mRemote.transact 進行轉發,mRemote 對象正是 Binder 驅動返回來的 Binder Proxy 對象,通過 Binder Proxy,Binder 驅動最終將調用處于 Binder Server 端 AMN 中的 onTransact 方法:
@Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {// 根據方法調用號 code 決定調用哪個方法switch (code) {case START_ACTIVITY_TRANSACTION:{...// 調用 startActivity 方法int result = startActivity(app, callingPackage, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, options);reply.writeNoException();reply.writeInt(result);return true;}...case START_SERVICE_TRANSACTION: {...ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);reply.writeNoException();ComponentName.writeToParcel(cn, reply);return true;}...} }1.1.8 ActivityManagerService.startActivity
AMN 是一個抽象類,它的 startActivity 為抽象方法,具體的實現在 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java 中:
@Override public final int startActivity(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId()); }1.2 小結
從 Launcher App 到 AMS 的調用過程中使用了 Binder IPC 機制,如果你已經看了上面提到的我之前寫的兩篇文章——借助 AIDL 理解 Android Binder 機制——Binder 來龍去脈和借助 AIDL 理解 Android Binder 機制——AIDL 的使用和原理分析,并且運行了文章中使用到的 Demo,你應該可以發現,相對于 AIDL 的調用過程,調用方 Launcher App 相當于 AIDL 過程中的 Activity 所在的 App,充當 Clinent 的角色;AMS 相當于遠程 Service 的角色,充當 Server 端角色,他們的調用過程總體上都是一樣的。
從 Launcher App 到 AMS 的時序圖如下:
2. AMS —— zygote
2.1 調用過程分析
2.1.1 ActivityManagerService.startActivityAsUser
接著從 AMS 的 startActivityAsUser 方法開始分析:
@Override public final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {enforceNotIsolatedCaller("startActivity");userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),userId, false, ALLOW_FULL_ONLY, "startActivity", null);// TODO: Switch to user app stacks here.// 調用 ActivityStarter 的 startActivityMayWait 方法return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,profilerInfo, null, null, bOptions, false, userId, null, null); }2.1.2 ActivityStarter.startActivityMayWait
繼續跟進 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java:
final int startActivityMayWait(IApplicationThread caller, int callingUid,String callingPackage, Intent intent, String resolvedType,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,Bundle bOptions, boolean ignoreTargetSecurity, int userId,IActivityContainer iContainer, TaskRecord inTask) {...synchronized (mService) {...// 調用 startActivityLocked 方法int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,aInfo, rInfo, voiceSession, voiceInteractor,resultTo, resultWho, requestCode, callingPid,callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,options, ignoreTargetSecurity, componentSpecified, outRecord, container,inTask);...return res;} }2.1.3 ActivityStarter.startActivityLocked
查看 startActivityLocked 方法:
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,String callingPackage, int realCallingPid, int realCallingUid, int startFlags,ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,TaskRecord inTask) {...// 調用 doPendingActivityLaunchesLocked 方法,傳入 false 參數doPendingActivityLaunchesLocked(false);...return err; }2.1.4 ActivityStarter.doPendingActivityLaunchesLocked
查看 doPendingActivityLaunchesLocked 方法:
final void doPendingActivityLaunchesLocked(boolean doResume) {while (!mPendingActivityLaunches.isEmpty()) {final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);final boolean resume = doResume && mPendingActivityLaunches.isEmpty();try {// 調用 startActivityUnchecked 方法final int result = startActivityUnchecked(pal.r, pal.sourceRecord, null, null,pal.startFlags, resume, null, null);postStartActivityUncheckedProcessing(pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord, mTargetStack);} catch (Exception e) {Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);pal.sendErrorResult(e.getMessage());}} }2.1.5 ActivityStarter.startActivityUnchecked
查看 startActivityUnchecked 方法:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {... // 調用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 方法mSupervisor.resumeFocusedStackTopActivityLocked(); ... return START_SUCCESS; }2.1.6 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);}final ActivityRecord r = mFocusedStack.topRunningActivityLocked();if (r == null || r.state != RESUMED) {// 調用 ActivityStack 的 resumeTopActivityUncheckedLocked 方法mFocusedStack.resumeTopActivityUncheckedLocked(null, null);}return false; }2.1.7 ActivityStack.resumeTopActivityUncheckedLocked
查看 ActivityStack 的 resumeTopActivityUncheckedLocked 方法:
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {...try {...// 調用 resumeTopActivityInnerLocked 方法result = resumeTopActivityInnerLocked(prev, options);} finally {mStackSupervisor.inResumeTopActivity = false;}return result; }2.1.8 ActivityStack.resumeTopActivityInnerLocked
查看 resumeTopActivityInnerLocked 方法:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {...final ActivityRecord next = topRunningActivityLocked();...if (next.app != null && next.app.thread != null) {...} else {...if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);// 調用 ActivityStackSupervisor 的 startSpecificActivityLocked 方法mStackSupervisor.startSpecificActivityLocked(next, true, true);}if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();return true; }2.1.9 ActivityStackSupervisor.startSpecificActivityLocked
回到 ActivityStackSupervisor 的 startSpecificActivityLocked 方法:
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {// 當前 Activity 附屬的 ApplicationProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);r.task.stack.setLaunchTime(r);// 如果 Application 已經運行if (app != null && app.thread != null) {try {if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0|| !"android".equals(r.info.packageName)) {app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,mService.mProcessStats);}realStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);}}// 啟動新進程mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true); }首先,在方法中獲取了當前 Activity 附屬的 Application,如果已經在運行了,說明這個 App 是已經被啟動過了的,這時候調用 realStartActivityLocked 方法就可以進入下一步的流程了,同一個 App 中不同 Activity 的相互啟動就是走的這個流程。當 Application 沒有運行的時候,就需要調用 AMS 的 startProcessLocked 方法啟動一個進程去承載它然后完成后續的工作,順便鋪墊一下,當新進程被啟動完成后還會調用回到這個方法,查看 AMS 的 startProcessLocked 方法:
2.1.10 ActivityManagerService.startProcessLocked
final ProcessRecord startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,String hostingType, ComponentName hostingName, boolean allowWhileBooting,boolean isolated, boolean keepIfLarge) {return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,null /* crashHandler */); }2.1.11 ActivityManagerService.startProcessLocked
調用 startProcessLocked 方法:
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler){...startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);checkTime(startTime, "startProcess: done starting proc!");return (app.pid != 0) ? app : null; }2.1.12 ActivityManagerService.startProcessLocked
調用 startProcessLocked 的重載方法:
private final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs){...try {...// 調用 Process 的 start 方法Process.ProcessStartResult startResult = Process.start(entryPoint,app.processName, uid, uid, gids, debugFlags, mountExternal,app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,app.info.dataDir, entryPointArgs);...} catch (RuntimeException e) {...} }2.1.13 Process.start
frameworks/base/services/core/java/android/os/Process.java:
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 abi,String instructionSet,String appDataDir,String[] zygoteArgs) {try {// 調用 startViaZygote 方法return startViaZygote(processClass, niceName, uid, gid, gids,debugFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, zygoteArgs);} catch (ZygoteStartFailedEx ex) {Log.e(LOG_TAG,"Starting VM process through Zygote failed");throw new RuntimeException("Starting VM process through Zygote failed", ex);} }2.1.14 Process.startViaZygote
查看 startViaZygote 方法:
private static ProcessStartResult startViaZygote(final String processClass,final String niceName,final int uid, final int gid,final int[] gids,int debugFlags, int mountExternal,int targetSdkVersion,String seInfo,String abi,String instructionSet,String appDataDir,String[] extraArgs)throws ZygoteStartFailedEx {synchronized(Process.class) {...// 調用 zygoteSendArgsAndGetResult 方法,傳入 openZygoteSocketIfNeeded 的返回值return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);} }2.1.15 Process.zygoteSendArgsAndGetResult、Process.openZygoteSocketIfNeeded
查看 zygoteSendArgsAndGetResult 方法:
private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args)throws ZygoteStartFailedEx {try {...final BufferedWriter writer = zygoteState.writer;final DataInputStream inputStream = zygoteState.inputStream;writer.write(Integer.toString(args.size()));writer.newLine();for (int i = 0; i < sz; i++) {String arg = args.get(i);writer.write(arg);writer.newLine();}writer.flush();// Should there be a timeout on this?ProcessStartResult result = new ProcessStartResult();// 等待 socket 服務端(即zygote)返回新創建的進程pid;result.pid = inputStream.readInt();result.usingWrapper = inputStream.readBoolean();if (result.pid < 0) {throw new ZygoteStartFailedEx("fork() failed");}return result;} catch (IOException ex) {zygoteState.close();throw new ZygoteStartFailedEx(ex);} }在 zygoteSendArgsAndGetResult 中等待 Socket 服務端,也就是 zygote 進程返回創建新進程的結果,這里 zygoteState 參數是由 openZygoteSocketIfNeeded 方法返回的,openZygoteSocketIfNeeded 方法則負責根據 abi 向 Zygote 進程發起連接請求:
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {if (primaryZygoteState == null || primaryZygoteState.isClosed()) {try {// 向主zygote發起connect()操作primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);} catch (IOException ioe) {throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);}}if (primaryZygoteState.matches(abi)) {return primaryZygoteState;}if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {try {// 當主zygote沒能匹配成功,則采用第二個zygote,發起connect()操作secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);} catch (IOException ioe) {throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);}}if (secondaryZygoteState.matches(abi)) {return secondaryZygoteState;}throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }2.2 小結
如果是從桌面新啟動一個 App 中的 Activity,此時是沒有進程去承載這個 App 的,因此需要通過 AMS 向 zygote 繼承發起請求去完成這個任務,AMS 運行在 system_server 進程中,它通過 Socket 向 zygote 發起 fock 進程的請求,從 AMS 開始的調用時序圖如下:
3. zygote —— ActivityThread
3.1 調用過程分析
3.1.1 ZygoteInit.main
在 Android 系統啟動流程分析 文中提到過 zygote 進程的其中一項任務就是:
調用 registerZygoteSocket() 函數建立 Socket 通道,使 zygote 進程成為 Socket 服務端,并通過 runSelectLoop() 函數等待 ActivityManagerService 發送請求創建新的應用程序進程。zygote 終于要再次上場了!接下來從 ZygoteInit.java 的 main 方法開始回顧一下 zygote 進程的工作:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java:
public static void main(String argv[]) {try {...runSelectLoop(abiList);....} catch (MethodAndArgsCaller caller) {caller.run();} catch (RuntimeException ex) {closeServerSocket();throw ex;} }3.1.2 ZygoteInit.runSelectLoop
查看 runSelectLoop 方法:
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {...// 循環讀取狀態while (true) {...for (int i = pollFds.length - 1; i >= 0; --i) {// 讀取的狀態不是客戶端連接或者數據請求時,進入下一次循環if ((pollFds[i].revents & POLLIN) == 0) {continue;}if (i == 0) {// i = 0 表示跟客戶端 Socket 連接上了ZygoteConnection newPeer = acceptCommandPeer(abiList);peers.add(newPeer);fds.add(newPeer.getFileDesciptor());} else {// i > 0 表示接收到客戶端 Socket 發送過來的請求// runOnce 方法創建一個新的應用程序進程boolean done = peers.get(i).runOnce();if (done) {peers.remove(i);fds.remove(i);}}}} }3.1.3 ZygoteConnection.runOnce
查看 frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java 的 runOnce 方法:
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {String args[];Arguments parsedArgs = null;FileDescriptor[] descriptors;try {// 讀取 socket 客戶端發送過來的參數列表args = readArgumentList();descriptors = mSocket.getAncillaryFileDescriptors();} catch (IOException ex) {// EOF reached.closeSocket();return true;}...try {// 將 socket 客戶端傳遞過來的參數,解析成 Arguments 對象格式parsedArgs = new Arguments(args);...// 同樣調用 Zygote.java 的 forkAndSpecialize 方法 fock 出子進程pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,parsedArgs.appDataDir);} catch (Exception e) {...}try {if (pid == 0) {// 子進程執行IoUtils.closeQuietly(serverPipeFd);serverPipeFd = null;// 進入子進程流程handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);return true;} else {// 父進程執行IoUtils.closeQuietly(childPipeFd);childPipeFd = null;return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);}} finally {IoUtils.closeQuietly(childPipeFd);IoUtils.closeQuietly(serverPipeFd);} }3.1.4 ZygoteConnection.handleChildProc
首先解析 Socket 客戶端傳過來的參數,Zygote.java 的 forkAndSpecialize 返回的 pid == 0 的時候表示此時在 fock 出來的子進程中執行,繼續調用 handleChildProc 方法,并將參數繼續層層傳遞:
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller {/*由于 fock 出來的 system_server 進程會復制 zygote 進程的地址空間,因此它也得到了 zygote進程中的 Socket,這個 Socket 對它來說并無用處,這里將其關閉 */closeSocket();ZygoteInit.closeServerSocket();...if (parsedArgs.niceName != null) {// 設置進程名Process.setArgV0(parsedArgs.niceName);}if (parsedArgs.invokeWith != null) {...} else {// 調用 RuntimeInit 的 zygoteInit 方法RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs, null);} }3.1.5 RuntimeInit.zygoteInit
查看 frameworks/base/core/java/com/android/internal/os/RuntimeInit.java 的 zygoteInit 方法:
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");// 重定向 log 輸出redirectLogStreams();// 初始化一些通用的設置commonInit(); /***通過 Native 層中 AndroidRuntime.cpp 的 JNI 方法最終調用 app_main.cpp 的 *onZygoteInit 方法啟動 Binder 線程池, 使 system_server 進程可以使用 Binder *與其他進程通信**/nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader); }3.1.6 RuntimeInit.applicationInit
繼續調用 applicationInit 方法:
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {...// 提取出參數里面的要啟動的類的名字invokeStaticMain(args.startClass, args.startArgs, classLoader); }3.1.7 RuntimeInit.invokeStaticMain
主要調用了 invokeStaticMain 方法:
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {Class<?> cl;try {/** className 為通過 Socket 客戶端(AMS)傳遞過來的一系列參數中的其中一個,這里獲取到的值為傳"com.android.app.ActivityThread",然后通過反射得到 ActivityThread 類 **/cl = Class.forName(className, true, classLoader);} catch (ClassNotFoundException ex) {throw new RuntimeException("Missing class when invoking static main " + className, ex);}Method m;try {// 找到 ActivityThread 類的 main 方法m = cl.getMethod("main", new Class[] { String[].class });} catch (NoSuchMethodException ex) {throw new RuntimeException("Missing static main on " + className, ex);} catch (SecurityException ex) {throw new RuntimeException("Problem getting static main on " + className, ex);}int modifiers = m.getModifiers();if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {throw new RuntimeException("Main method is not public and static on " + className);}/** 將 main 方法包裝在 ZygoteInit.MethodAndArgsCaller 類中并作為異常拋出捕獲異常的地方在上一小節中 ZygoteInit.java 的 main 方法 **/throw new ZygoteInit.MethodAndArgsCaller(m, argv); }3.1.8 MethodAndArgsCaller.run
回到 ZygoteInit 的 main 方法:
public static void main(String argv[]) {...closeServerSocket();} catch (MethodAndArgsCaller caller) {// 接收到 caller 對象后調用它的 run 方法caller.run();} catch (RuntimeException ex) {Log.e(TAG, "Zygote died with exception", ex);closeServerSocket();throw ex;} }跟 system_server 進程的啟動過程一樣,這里同樣通過拋出異常的方式來清空調用 ActivityThread.main 之前的方法棧幀。
ZygoteInit 的 MethodAndArgsCaller 類是一個 Exception 類,同時也實現了 Runnable 接口:
public static class MethodAndArgsCaller extends Exceptionimplements Runnable {private final Method mMethod;private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {mMethod = method;mArgs = args;}public void run() {try {// 調用傳遞過來的 mMethodmMethod.invoke(null, new Object[] { mArgs });} catch (IllegalAccessException ex) {throw new RuntimeException(ex);} catch (InvocationTargetException ex) {...}} }3.1.9 ActivityThread .main
最后通過反射調用到 ActivityThread 的 main 方法:
public static void main(String[] args) {...Environment.initForCurrentUser();...Process.setArgV0("<pre-initialized>");// 創建主線程 LooperLooper.prepareMainLooper();ActivityThread thread = new ActivityThread();// attach 到系統進程thread.attach(false);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}// 主線程進入輪詢狀態Looper.loop();// 拋出異常說明輪詢出現問題throw new RuntimeException("Main thread loop unexpectedly exited"); }3.2 小結
zygote 進程作為 Socket 服務端在接收到作為客戶端的 AMS 發送過來的請求和參數之后,fock 出新的進程并根據各種參數進程了初始化的工作,這個過程和 zygote 啟動 system_server 進程的過程如出一轍,時序圖如下所示:
4. ActivityThread —— Activity
4.1 調用過程分析
4.1.1 ActivityThread.attach
上一小節的最后,ActivityThread 的 main 通過反射被運行起來了,接著會調用 ActivityThread 的 attach 方法:
private void attach(boolean system) {...mSystemThread = system;if (!system) {...// 獲取 ActivityManagerProxy 對象final IActivityManager mgr = ActivityManagerNative.getDefault();try {// 通過 Binder 調用 AMS 的 attachApplication 方法mgr.attachApplication(mAppThread);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}} else {...}... }這里,我們再一次通過 Binder IPC 機制跟 AMS 通信,通信模型跟前面 Launcher App 調用 AMS 的 startActivity 方法一樣,getDefault 過程不重復分析,這次是調用了 AMS 的 attachApplication 方法,注意這里將 ApplicationThead 類型的 mAppThread 對象作為參數傳遞了過去,ApplicationThead 是 ActivityThread 的一個內部類,后面我們會講到,先查看 AMP 的 attachApplication 方法:
4.1.2 ActivityManagerProxy.attachApplication
public void attachApplication(IApplicationThread app) throws RemoteException {...// 調用 asBinder 方法使其能夠跨進程傳輸data.writeStrongBinder(app.asBinder());// 通過 transact 方法將數據交給 Binder 驅動mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0); reply.readException();data.recycle();reply.recycle(); }4.1.3 ActivityManagerNative.onTransact
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {switch (code) {...case ATTACH_APPLICATION_TRANSACTION: {data.enforceInterface(IActivityManager.descriptor);// 獲取 ApplicationThread 的代理對象,這里返回的是 ApplicationThreadNative(ATN)// 的內部類:ApplicationThreadProxy(ATP) 對象IApplicationThread app = ApplicationThreadNative.asInterface(data.readStrongBinder());if (app != null) {// 委托給 AMS 執行attachApplication(app);}reply.writeNoException();return true;}...} }asInterface 將 ActivityThread 對象轉換成了 ApplicationThreadNative(ATN) 的 Binder 代理對象 ApplicationThreadProxy(ATP),并作為參數傳給 attachApplication 方法,其中 ATP 是 ATN 的內部類。
4.1.4 ActivityManagerService.attachApplication
public final void attachApplication(IApplicationThread thread) {synchronized (this) {int callingPid = Binder.getCallingPid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid);Binder.restoreCallingIdentity(origId);} }4.1.5 ActivityManagerService.attachApplicationLocked
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {ProcessRecord app;...try {// 綁定死亡通知AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);thread.asBinder().linkToDeath(adr, 0);app.deathRecipient = adr;} catch (RemoteException e) {app.resetPackageList(mProcessStats);// 如果 system_server 進程死亡則重新啟動進程startProcessLocked(app, "link fail", processName); return false;}...try {...// 獲取應用appInfoApplicationInfo appInfo = app.instrumentationInfo != null? app.instrumentationInfo : app.info;...// 綁定應用thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(mConfiguration), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked());...} catch (Exception e) {app.resetPackageList(mProcessStats);app.unlinkDeathRecipient();// bindApplication 失敗也要重啟進程startProcessLocked(app, "bind fail", processName);return false;}// 如果是 Activity: 檢查最頂層可見的Activity是否等待在該進程中運行if (normalMode) {try {if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {badApp = true;}}// 如果是 Service: 尋找所有需要在該進程中運行的服務if (!badApp) {try {didSomething |= mServices.attachApplicationLocked(app, processName);} catch (Exception e) {badApp = true;}}// 如果是 BroadcastReceiver: 檢查是否在這個進程中有下一個廣播接收者if (!badApp && isPendingBroadcastProcessLocked(pid)) {try {didSomething |= sendPendingBroadcastsLocked(app);} catch (Exception e) {badApp = true;}}// 檢查是否在這個進程中有下一個 backup 代理if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {ensurePackageDexOpt(mBackupTarget.appInfo.packageName);try {thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,compatibilityInfoForPackageLocked(mBackupTarget.appInfo),mBackupTarget.backupMode);} catch (Exception e) {badApp = true;}}if (badApp) { // 殺掉 badAppapp.kill("error during init", true);handleAppDiedLocked(app, false, true);return false;}if (!didSomething) {// 更新 adj(組件的權值)updateOomAdjLocked(); }return true; }首先,通過 ATP 使用 Binder 向 ATN 發起 bindApplication 請求,然后通過 normalMode 字段判斷是否為 Activity,如果是則執行 ActivityStackSupervisor 的 attachApplicationLocked 方法。
4.1.5.1 ActivityThread.java::ApplicationThread.bindApplication
thread 對象類型是 ATP,通過 Binder 驅動調到了 ATN 的方法,ATN 是一個抽象類,它的實現都委托給了 ApplicationThread(這跟 AMS 跟 AMN 的關系一樣),ApplicationThread 作為 ActivityThread 的內部類存在,它的 binderApplication 方法如下:
ActivityThread.java::ApplicationThread:
public final void bindApplication(String processName, ApplicationInfo appInfo,List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo,Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,IUiAutomationConnection instrumentationUiConnection, int debugMode, booleanenableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configurationconfig, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {if (services != null) {// 將services緩存起來, 減少binder檢索服務的次數ServiceManager.initServiceCache(services);}...// 發送消息 H.BIND_APPLICATION 給 Handler 對象sendMessage(H.BIND_APPLICATION, data); }H 是 ActivityThread 中的一個 Handler 對象,用于處理發送過來的各種消息:
private class H extends Handler {public static final int BIND_APPLICATION = 110;public void handleMessage(Message msg) {...case BIND_APPLICATION:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;...} }調用了 handleBindApplication 方法:
private void handleBindApplication(AppBindData data) {// 獲取 LoadedApk 對象data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);...// 創建 ContextImpl 上下文final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);...// 創建 Instrumentation 對象if (data.instrumentationName != null) {...} else {mInstrumentation = new Instrumentation();}try {// 調用 LoadedApk 的 makeApplication 方法創建 ApplicationApplication app = data.info.makeApplication(data.restrictedBackupMode, null);mInitialApplication = app;...mInstrumentation.onCreate(data.instrumentationArgs);// 調用 Application.onCreate 方法mInstrumentation.callApplicationOnCreate(app);} finally {StrictMode.setThreadPolicy(savedPolicy);} }4.1.5.2 ActivityStackSupervisor.attachApplicationLocked
在 4.1.4 小節中通過 Binder 向 ActivityThread 發起 bindApplication 請求后,會根據啟動組件的類型去做相應的處理,如果是 Acitivity,則會調用 ActivityStackSupervisor 的 attachApplicationLocked 方法:
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {final String processName = app.processName;boolean didSomething = false;for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {final ActivityStack stack = stacks.get(stackNdx);if (!isFrontStack(stack)) {continue;}// 獲取前臺stack中棧頂第一個非 finishing 狀態的 ActivityActivityRecord hr = stack.topRunningActivityLocked(null);if (hr != null) {if (hr.app == null && app.uid == hr.info.applicationInfo.uid && processName.equals(hr.processName)) {try {// 真正的啟動 Activityif (realStartActivityLocked(hr, app, true, true)) {didSomething = true;}} catch (RemoteException e) {throw e;}}}}}...return didSomething; }4.1.5.2.1 ActivityStackSupervisor.realStartActivityLocked
前面 2.1.8 ActivityStackSupervisor.startSpecificActivityLocked 小節中分析過,如果當前 Activity 依附的 Application 已經被啟動,則調用 realStartActivityLocked 方法,否則創建新的進程,再創建新的進程之后,兩個流程的在這里合并起來了:
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {...final ActivityStack stack = task.stack;try {...app.forceProcessStateUpTo(mService.mTopProcessState);// 通過 Binder 調用 ApplicationThread 的 scheduleLaunchActivity 方法app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);...} catch (RemoteException e) {if (r.launchFailed) {// 第二次啟動失敗,則結束該 ActivitymService.appDiedLocked(app);stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,"2nd-crash", false);return false;}// 第一個啟動失敗,則重啟進程app.activities.remove(r);throw e;}...return true; }這里有一次使用 Binder 調用 ApplicationThread 的 scheduleLaunchActivity 方法。
4.1.5.2.2 ApplicationThread.scheduleLaunchActivity
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {...updateProcessState(procState, false);ActivityClientRecord r = new ActivityClientRecord();...sendMessage(H.LAUNCH_ACTIVITY, r);}上面提到過,H 是 ActivityThread 中一個 Handler 類,它接收到 LAUNCH_ACTIVITY 消息后會調用 handleLaunchActivity 方法。
4.1.5.2.3 ActivityThread.handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {...// 初始化 WMSWindowManagerGlobal.initialize();// 執行 performLaunchActivity 方法Activity a = performLaunchActivity(r, customIntent);if (a != null) {r.createdConfig = new Configuration(mConfiguration);Bundle oldState = r.state;// 執行 handleResumeActivity 方法,最終調用 onStart 和 onResume 方法handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed);if (!r.activity.mFinished && r.startsNotResumed) {r.activity.mCalled = false;mInstrumentation.callActivityOnPause(r.activity);r.paused = true;}} else {// 停止該 ActivityActivityManagerNative.getDefault().finishActivity(r.token, Activity.RESULT_CANCELED, null, false);} }4.1.4.2.4 ApplicationThread.performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {...Activity activity = null;try {java.lang.ClassLoader cl = r.packageInfo.getClassLoader();// Instrumentation 中使用反射創建 Activityactivity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);...} catch (Exception e) {...}try {// 創建 Application 對象并調用 Application 的 onCreate 方法Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (activity != null) {...// attach 到 Window 上activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor);if (customIntent != null) {activity.mIntent = customIntent;}r.lastNonConfigurationInstances = null;activity.mStartedActivity = false;int theme = r.activityInfo.getThemeResource();if (theme != 0) {// 設置主題activity.setTheme(theme);}activity.mCalled = false;if (r.isPersistable()) {// 重新創建的 ActivitymInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {// 第一次創建的 ActivitymInstrumentation.callActivityOnCreate(activity, r.state);}...}...} catch (Exception e) {...}return activity; }4.1.5.2.5 Instrumentation.callActivityOnCreate
public void callActivityOnCreate(Activity activity, Bundle icicle,PersistableBundle persistentState) {prePerformCreate(activity);// 調用 Activity 的 performCreate 方法activity.performCreate(icicle, persistentState);postPerformCreate(activity); }4.1.5.2.6 Activity.performCreate
final void performCreate(Bundle icicle, PersistableBundle persistentState) {restoreHasCurrentPermissionRequest(icicle);onCreate(icicle, persistentState);mActivityTransitionState.readState(icicle);performCreateCommon(); }終于,onCreate 方法被調用了!!!
4.2 小結
從 ActivityThread 到最終 Activity 被創建及生命周期被調用,核心過程涉及到了三次 Binder IPC 過程,分別是:ActivityThread 調用 AMS 的 attachApplication 方法、AMS 調用 ApplicationThread 的 bindApplication 方法、ASS 調用 Application 的 attachApplicationLocked 方法,整個過程的時序圖如下:
5. 總結
縱觀整個過程,從 Launcher 到 AMS、從 AMS 再到 Zygote、再從 Zygote 到 ActivityThread,最后在 ActivitThread 中層層調用到 Activity 的生命周期方法,中間涉及到了無數的細節,但總體上脈絡還是非常清晰的,各個 Android 版本的 Framework 層代碼可以某些過程的實現不太一樣,但是整個調用流程大體上也是相同的,借用 Gityuan 大神的一張圖作為結尾:
系列文章
AJie:按下電源鍵后竟然發生了這一幕 —— Android 系統啟動流程分析?zhuanlan.zhihu.comAJie:App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析?zhuanlan.zhihu.comAJie:屏幕上內容究竟是怎樣畫出來的 —— Android View 工作原理詳解?zhuanlan.zhihu.com參考文章
startActivity啟動過程分析 - Gityuan博客 | 袁輝輝的技術博客
Android深入四大組件(一)應用程序啟動過程(前篇)
如果你對文章內容有疑問或者有不同的意見,歡迎留言,我們一同探討。總結
以上是生活随笔為你收集整理的c++builder启动了怎么停止_App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 坐地铁可以刷学生卡吗_在沈阳办的公交卡能
- 下一篇: aoe网最早开始时间和最迟开始时间_关键