日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++builder启动了怎么停止_App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析...

發布時間:2024/1/23 c/c++ 84 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 启动流程分析...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

激情自拍av | 午夜精品久久久 | 婷婷色站 | 精品一区二区三区久久久 | 久久女同性恋中文字幕 | 免费成人黄色片 | 夜夜婷婷 | 丁香久久 | www.xxx.性狂虐 | 美女网站在线播放 | 丁香六月五月婷婷 | 国产成人精品久久亚洲高清不卡 | 992tv在线观看网站 | 久久免费视频8 | av在线官网 | 超碰在线公开 | 天天干天天操人体 | 色婷婷激情综合 | 日韩在线字幕 | 日本二区三区在线 | 美女精品久久久 | 亚洲视频在线观看免费 | 五月开心网 | 在线成人高清电影 | 中文字幕第一页在线 | 久久久久影视 | 国产a高清 | 亚洲精品国产精品乱码不99热 | 国产 在线观看 | 亚洲黄色网络 | 日韩毛片在线一区二区毛片 | 视频一区二区在线观看 | 免费高清影视 | 日韩视频一区二区在线 | 免费黄色av片| 美女视频黄的免费的 | 激情一区二区三区欧美 | 天天狠狠操 | 99热亚洲精品| 国产精品三级视频 | 欧美性生活一级片 | 午夜影院一区 | 成人在线免费视频观看 | 在线观看91精品视频 | av黄色免费在线观看 | 欧美成人一区二区 | 欧美一区二区在线看 | 国产美女免费观看 | 日韩在线免费播放 | 久久久久色 | 日本不卡123区 | 99久久久久免费精品国产 | 涩涩网站在线看 | 超碰在线日韩 | 成年人在线看视频 | 日韩高清免费无专码区 | 九九久| 精品国产视频在线观看 | 国产91勾搭技师精品 | 久久视| 黄色三级在线看 | 亚洲精品99久久久久久 | 黄网站app在线观看免费视频 | 日韩午夜剧场 | 在线观看欧美成人 | 操操操日日日 | 免费一级特黄毛大片 | 国产传媒中文字幕 | 久久理伦片 | 国产在线毛片 | 在线国产日韩 | 中文字幕高清免费日韩视频在线 | 久草热久草视频 | 日韩精品一区二区在线视频 | 欧美巨大荫蒂茸毛毛人妖 | 一区二区三区日韩视频在线观看 | 在线电影中文字幕 | 日本性生活一级片 | 欧美地下肉体性派对 | 亚洲精品乱码久久久久久蜜桃动漫 | 日韩欧美在线国产 | 人人爱爱人人 | 日本少妇高清做爰视频 | 日本精品视频在线播放 | 久久精品韩国 | 国产小视频福利在线 | 久久五月婷婷综合 | 天天操天天弄 | 婷婷五天天在线视频 | 亚洲激情精品 | 国际精品久久久久 | 天天综合网在线观看 | 在线电影 一区 | 婷久久 | 中文字幕精品一区久久久久 | 亚洲综合视频在线 | 麻豆久久| 中文国产在线观看 | 国产精品女同一区二区三区久久夜 | 国产精品美女在线 | 国产精品婷婷 | 日韩黄色在线 | 国产婷婷在线观看 | 综合网伊人 | 精品国产视频一区 | 97av影院 | 97小视频| 一级a性色生活片久久毛片波多野 | 日本狠狠干 | 特级免费毛片 | 伊人天天狠天天添日日拍 | 亚洲精品乱码久久久久久蜜桃不爽 | 91在线视频在线观看 | 在线国产片 | 中文字幕在线观看一区二区三区 | 免费在线观看视频一区 | 91九色免费视频 | 日韩精品影视 | 国产精品美女久久久久aⅴ 干干夜夜 | 亚洲国产网站 | 激情五月***国产精品 | 在线精品亚洲 | 国产亚洲精品久久久久久移动网络 | 久久久久97国产 | av看片在线 | 亚洲欧美综合精品久久成人 | 色综合www| 91免费高清观看 | 黄色一级大片在线免费看国产一 | 国产免码va在线观看免费 | 四川妇女搡bbbb搡bbbb搡 | 国产区精品 | 成人a大片 | 亚洲人xxx | 精品久久一区 | 精品一二三四视频 | 午夜久久福利视频 | 在线观看免费国产小视频 | 国产高清精品在线 | 亚洲精品国产精品国自产观看浪潮 | 久精品视频在线 | 高清视频一区二区三区 | 国产成人一区二区三区久久精品 | 欧美91精品久久久久国产性生爱 | 亚洲最新在线 | 九九视频在线 | 中文字幕 国产精品 | 天天射综合网站 | 一区二区 不卡 | 亚洲精品一区二区精华 | 国产精品videossex国产高清 | 91手机视频 | 视频一区二区免费 | 精品一区二区免费在线观看 | 最近日韩免费视频 | 中文字幕在线观看视频免费 | 91亚洲永久精品 | 日韩欧美在线视频一区二区三区 | 91夫妻自拍| 欧美在线一 | 欧美激情在线网站 | 亚洲一区视频在线播放 | 国产小视频国产精品 | 亚洲精品免费在线视频 | 五月婷婷色综合 | 免费成人短视频 | 国产精品久久久久久久久久久杏吧 | 在线观看爱爱视频 | 99热这里精品 | 精品人人爽 | 超碰在线人人 | 国产精品人成电影在线观看 | 日韩免费b | 97福利在线| 日韩免费电影网站 | 国产精品久久久久久久免费大片 | 热久久最新地址 | 国产成人av福利 | 婷婷综合电影 | 亚洲视频在线看 | 免费合欢视频成人app | 亚洲欧美在线综合 | 欧美精品久久久久久 | 国产一级在线观看 | 亚洲国产网站 | 你操综合| 日韩av进入 | 黄色在线小网站 | 欧美在线观看视频免费 | 91麻豆精品国产午夜天堂 | 日本精品午夜 | 中文字幕av免费在线观看 | 99超碰在线观看 | 日韩久久久久久久久久久久 | 欧美日韩在线精品 | 久久国产电影院 | 久热av在线| 五月婷婷影院 | 日韩av影视| 亚洲精品视频网 | 色橹橹欧美在线观看视频高清 | 国产 中文 日韩 欧美 | 久热这里有精品 | 激情五月激情综合网 | 精品视频网站 | 美女国内精品自产拍在线播放 | 亚洲有 在线 | 日韩av在线一区二区 | 亚洲国产免费看 | 91天天操 | 日本爱爱片 | 碰超人人| 久久99深爱久久99精品 | 久久艹在线观看 | 香蕉91视频 | 色亚洲网 | 这里只有精品视频在线 | 中文字幕在线中文 | 香蕉久草在线 | 在线观看亚洲免费视频 | 五月婷婷狠狠 | 亚洲人久久久 | 日韩在线一区二区免费 | 2019中文字幕第一页 | 国产精品久久久一区二区三区网站 | 在线观看一区 | 一区二区三区韩国免费中文网站 | 国产传媒一区在线 | 婷婷av色综合 | 久久免费看av | www.com操| 最新中文字幕在线资源 | 91看片淫黄大片一级在线观看 | 国产专区在线看 | 日韩欧美高清在线 | 中文字幕91视频 | 99精品视频免费看 | 日日久视频 | 在线观看一区二区精品 | 天天干,天天干 | 日韩精品免费一区二区 | 色噜噜狠狠狠狠色综合久不 | 久久国产精品免费一区二区三区 | 99热这里有精品 | 午夜美女视频 | 蜜桃av久久久亚洲精品 | 精品久久久久久久久久久院品网 | 色婷婷综合视频在线观看 | 中文字幕久久精品亚洲乱码 | 手机成人在线电影 | 国内精品久久久久久中文字幕 | 久久99国产综合精品免费 | 亚洲精品在线观看av | 国产精品久久久久久麻豆一区 | 91在线视频观看免费 | 国产亚洲精品女人久久久久久 | 激情视频久久 | 91天天操 | 亚洲精品合集 | 91片网| 国产在线精品一区 | 久久精品网站免费观看 | 97品白浆高清久久久久久 | 久久精品男人的天堂 | 免费在线观看a v | 波多野结衣资源 | 欧美午夜视频在线 | 成人福利在线播放 | 欧美激情视频一区二区三区免费 | 午夜久久久久久久久久影院 | 中文字幕大全 | 日韩欧美99 | 色综合久久中文字幕综合网 | 米奇影视7777 | 中文字幕在线影院 | 人人玩人人爽 | 亚洲小视频在线观看 | 天天草网站 | 欧美片网站yy | 日韩精品一区二区免费 | 日韩大陆欧美高清视频区 | 97色涩 | 国产成人精品一区二区三区免费 | 在线观看视频国产一区 | 国内精品在线观看视频 | 一级α片免费看 | 天天综合色| 日本黄色免费电影网站 | 色综合综合 | 国产色拍拍拍拍在线精品 | 国产综合香蕉五月婷在线 | 国产片免费在线观看视频 | 国产一二区精品 | 成人久久视频 | 麻豆系列在线观看 | 91视频在线自拍 | 亚洲区视频在线观看 | 婷婷激情在线观看 | 久久综合给合久久狠狠色 | 岛国av在线免费 | 久久久久国产精品厨房 | 97精品伊人| 丁香婷婷激情网 | 三级黄色欧美 | 欧美色综合 | 日韩欧美一区二区在线观看 | 日韩网站在线 | 久久久网址 | 婷婷丁香自拍 | 一区二区精品在线 | 2023国产精品自产拍在线观看 | 成人免费视频播放 | 亚洲一区二区三区miaa149 | 亚洲国产婷婷 | 伊人天天干 | 久久精品欧美日韩精品 | 三级黄色免费片 | 国产在线观看中文字幕 | 婷婷色吧 | 激情网色 | 天天综合网久久 | 香蕉精品视频在线观看 | 免费在线视频一区二区 | 国产一区av在线 | 天天综合视频在线观看 | 四虎影视成人 | 玖玖精品在线 | 亚洲精品美女久久久久网站 | 久久久综合精品 | 欧美动漫一区二区三区 | 99热最新网址| 色噜噜狠狠色综合中国 | 久久综合99| 福利视频一区二区 | 96精品高清视频在线观看软件特色 | 国内久久久久 | 国产成人一区二区三区电影 | 午夜精品区 | 最新91在线视频 | 日韩高清久久 | 亚洲精品国产成人av在线 | 91字幕| 国产精品日韩久久久久 | 狠狠ri | 免费网址你懂的 | 欧美极度另类 | 永久中文字幕 | 天无日天天操天天干 | 久久久综合精品 | 在线观看色网 | 中文字幕一区二区三区四区久久 | a级国产乱理论片在线观看 特级毛片在线观看 | 六月天综合网 | 久久免费视屏 | 欧美在线91| 99久久久久久 | 夜夜操狠狠干 | 精品国产伦一区二区三区免费 | 俺要去色综合狠狠 | 狠狠干狠狠久久 | 国产一区二区三精品久久久无广告 | 国产小视频网站 | 午夜精品一二区 | 天天天在线综合网 | 在线观看久 | 九九热中文字幕 | 在线观看日韩国产 | 国产日本在线播放 | 丁香亚洲 | 在线看片日韩 | 亚洲韩国一区二区三区 | 天天综合成人 | 美女免费网站 | 亚洲四虎 | 亚洲另类在线视频 | 天天综合网天天 | 日韩欧美高清免费 | 亚洲精选视频免费看 | 最近最新mv字幕免费观看 | 天堂久久电影网 | 国产成年免费视频 | 欧美在线一二 | 国产视频久久久 | 国产手机在线观看视频 | 激情五月色播五月 | 久久一区二区三区四区 | 丁香综合激情 | 国产成人久久精品77777综合 | 怡红院久久 | 亚洲女人天堂成人av在线 | 免费观看国产精品视频 | 久草视频免费在线观看 | 久久国内精品99久久6app | 又黄又色又爽 | 国产精品自在线 | 精品国产区 | 成人在线中文字幕 | 最新日韩视频在线观看 | 国产一区自拍视频 | 毛片网站在线 | www.五月激情.com | 免费黄在线观看 | 国产日韩视频在线播放 | 免费在线观看视频a | va视频在线观看 | 中文在线最新版天堂 | 成人免费观看电影 | 亚洲资源视频 | 在线观看黄色国产 | 日韩大陆欧美高清视频区 | 中文字幕欧美日韩va免费视频 | 日韩欧美国产精品 | 久久综合免费视频影院 | 国产 精品 资源 | 久草av在线播放 | 久久久国产一区 | 日韩精品亚洲专区在线观看 | 在线观看中文 | 婷婷色资源| 九九精品视频在线观看 | 国产一级片在线播放 | 欧美一区二区伦理片 | 国色天香在线 | 国产精品2020 | 欧美疯狂性受xxxxx另类 | 九九热久久免费视频 | 91在线看网站 | 成人黄色av网站 | 午夜视频日本 | 国产成人免费高清 | 在线免费观看欧美日韩 | 午夜国产福利在线 | 国产成人一区二区三区在线观看 | 69av免费视频| 国产破处在线视频 | 中文字幕韩在线第一页 | 国产精品久久久久久久久久免费看 | 九色在线视频 | 91九色视频观看 | 日韩三级视频在线观看 | 一区二区三区免费在线播放 | 欧美日韩久久一区 | 色综合天天狠天天透天天伊人 | 日韩亚洲精品电影 | 精品视频一区在线观看 | 日韩中文字幕免费 | 碰超在线97人人 | 香蕉久久久久 | 99精品国产一区二区三区不卡 | 久久精品艹 | 天天色天天骑天天射 | 免费av在线 | 在线日韩一区 | 国产小视频免费在线网址 | 99热免费在线 | 最近日本mv字幕免费观看 | 少妇按摩av | 色综合五月 | 国产不卡精品视频 | 欧美日韩一区二区免费在线观看 | 成年免费在线视频 | 激情欧美一区二区三区 | 久久99国产精品视频 | 免费高清看电视网站 | 中文在线免费视频 | 黄色三级在线 | 国产精品久久久久久久久久白浆 | www黄com| 国产成人久久精品亚洲 | 日韩在线观看第一页 | 丁香视频 | 欧美一区视频 | 黄色aaa级片| 91亚洲精品久久久中文字幕 | 国产做a爱一级久久 | 国内三级在线观看 | 中文字幕高清视频 | 国产精品福利在线观看 | 日韩大片在线免费观看 | 韩国三级一区 | 久久人人干 | 欧美综合久久 | 国产视频在线观看一区 | 国产精品第一视频 | 99久久精品国产一区二区三区 | 精品国产网址 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 国产免费成人 | 黄色三级免费网址 | 永久免费毛片 | 久久精品牌麻豆国产大山 | 国产精品免费在线观看视频 | 五月婷婷久 | 国产在线精品观看 | 欧美午夜性 | 久久久久久久99精品免费观看 | 99热这里只有精品8 久久综合毛片 | 伊人亚洲综合网 | 超碰人人草人人 | 久久久久高清 | 亚洲最大成人免费网站 | 噜噜色官网 | 午夜婷婷在线观看 | 91电影福利 | 9999精品免费视频 | 欧美一区二区三区免费观看 | 91麻豆精品国产午夜天堂 | 国产在线精品一区二区不卡了 | 国内精品久久久久久久久久 | 免费在线观看黄色网 | 国产成人三级一区二区在线观看一 | 午夜久久成人 | 97在线观看免费 | www.99热精品 | 狠狠插天天干 | 综合网婷婷 | 欧美日性视频 | 欧美日韩亚洲在线 | 国产精品男女啪啪 | 亚洲视频精选 | 91视频91蝌蚪 | www.888.av| 日韩电影在线观看一区 | 国产日韩精品一区二区三区在线 | 97电影网站 | 精品一区精品二区 | 中文字幕亚洲欧美 | 国产精品男女视频 | 国产a高清 | 国产精品视频永久免费播放 | 日韩av电影免费在线观看 | 三上悠亚一区二区在线观看 | 成年人免费在线 | 天天综合网国产 | 五月婷激情 | 右手影院亚洲欧美 | 国产无遮挡又黄又爽馒头漫画 | 欧美精品亚州精品 | 国产综合在线视频 | 成年人国产精品 | 美女网站在线播放 | 91黄色视屏| 激情 亚洲 | 国产中文字幕在线播放 | 色多多污污| 香蕉免费在线 | 在线成人中文字幕 | 久久久久免费精品国产小说色大师 | 日本久久成人中文字幕电影 | 久久91久久久久麻豆精品 | 日韩av一区二区在线播放 | 亚洲电影自拍 | 日产乱码一二三区别免费 | 人人爽人人澡人人添人人人人 | 免费观看丰满少妇做爰 | 在线只有精品 | 日韩成片 | 四虎国产视频 | 99九九99九九九视频精品 | 欧美激情h | 免费福利在线 | 夜夜爽天天爽 | 成人中文字幕+乱码+中文字幕 | 欧美 亚洲 另类 激情 另类 | 国产精品视频永久免费播放 | 日本久久中文字幕 | 久久婷婷国产色一区二区三区 | 欧美在线91| 在线看成人 | 超碰av在线免费观看 | 日韩理论 | 国产99一区二区 | 91九色视频在线 | 免费视频久久久久久久 | 日韩高清av在线 | 婷婷久月 | 亚洲影视资源 | 精品999在线观看 | 天天夜操 | 国产精品久久久久久999 | 97免费在线观看视频 | 国产一级在线看 | 婷婷久久国产 | 国产精品一区二区三区观看 | 精品国产一二三四区 | 国产精久久久久久久 | 91色亚洲 | 国产91精品一区二区绿帽 | 久久久久久久久久久电影 | 中文字幕在线观看完整 | 在线国产视频 | 最近中文字幕完整视频高清1 | 91精品一| 欧美日韩国产一区二区在线观看 | 国产一区二区三区免费在线观看 | 精品久久五月天 | 337p欧美 | 最新99热 | 99色在线视频 | 视频二区| 成人在线视频你懂的 | 亚洲jizzjizz日本少妇 | 最近中文国产在线视频 | 色中色综合 | av成人免费| 在线观看中文字幕 | 国产成人一区二区三区免费看 | 9在线观看免费高清完整 | 欧美日韩精品综合 | 国产日本高清 | 毛片网站在线 | 三级a毛片 | 热久久精品在线 | 国产黄色理论片 | 色橹橹欧美在线观看视频高清 | 国产精品久久久免费看 | 久久九九九九 | 亚洲综合视频在线 | 色偷偷男人的天堂av | 久草在线费播放视频 | 91在线国产观看 | 国产精品9999久久久久仙踪林 | 欧美激情精品久久久久久免费 | 免费观看丰满少妇做爰 | 免费看的黄色 | 91成年视频 | 视频在线日韩 | 亚洲高清在线精品 | 亚洲国产中文字幕在线视频综合 | 午夜久久福利视频 | 国产99爱| 中文字幕高清有码 | 俺要去色综合狠狠 | 日韩网站在线播放 | av色一区 | 日韩免费视频线观看 | 欧美日韩在线免费视频 | 麻豆果冻剧传媒在线播放 | 亚洲欧美乱综合图片区小说区 | 中文字幕资源网 国产 | 国产免费叼嘿网站免费 | 日韩三级视频在线观看 | 91视频免费看 | 国产香蕉久久精品综合网 | 日本巨乳在线 | 岛国片在线 | 亚州国产精品久久久 | 中文字幕在线播放日韩 | 国产精品成人在线 | 国产午夜精品理论片在线 | 深爱激情五月网 | 久久久精品网 | 天天干天天射天天插 | 日韩高清av | 97视频中文字幕 | 91激情视频在线播放 | 西西人体4444www高清视频 | 欧美在线观看视频一区二区 | 三级在线国产 | 草久久av| 美女黄频在线观看 | 中文字幕亚洲国产 | 欧美日韩中文字幕综合视频 | 日韩三级成人 | 综合激情网 | 国产精品粉嫩 | 国产精品网站一区二区三区 | 国产精品久久久久久久久久久久午夜片 | 五月婷婷六月丁香在线观看 | 伊人网综合在线观看 | 免费h视频| 精精国产xxxx视频在线播放 | 欧美不卡视频在线 | 日韩精品一区二区免费视频 | 精品免费观看视频 | 免费在线国产视频 | 国产精品白丝jk白祙 | 国产视频欧美视频 | 日韩一区二区免费视频 | 亚洲欧美国产精品18p | 中文字幕日韩精品有码视频 | 亚洲经典视频 | 国产精品第三页 | 五月天六月婷 | 视频二区在线 | 91香蕉嫩草| 久久网址| 手机成人在线 | 国产不卡在线 | 国产日韩欧美综合在线 | 日本中文字幕在线一区 | a在线观看国产 | 国产一级片一区二区三区 | 国产一区二区免费看 | 亚洲精品男人的天堂 | 成人av地址 | 色片网站在线观看 | 一区二区视频免费在线观看 | 四虎国产| 久久国产精品影片 | 成年人黄色免费视频 | 天天操天天射天天爱 | 91桃色免费视频 | 久久国产精品99精国产 | 丁香六月五月婷婷 | 91av电影在线观看 | 亚洲三级视频 | 亚洲精品456在线播放 | 日韩欧美一区二区三区视频 | 狠狠狠操 | 久久精品牌麻豆国产大山 | 成人av动漫在线观看 | www.狠狠干| av免费在线观 | 亚洲一区二区麻豆 | 久久国产视频网 | 九九热在线视频免费观看 | 国产精品久久久久久久久蜜臀 | 91大神精品视频 | 97超碰人人模人人人爽人人爱 | 在线免费观看黄色av | 国产99久久九九精品免费 | 国产一区二区三区 在线 | 成人免费视频视频在线观看 免费 | 久久精品视频日本 | 97在线观看免费高清完整版在线观看 | 日批网站免费观看 | 日韩精品中文字幕有码 | 国产xxxx做受性欧美88 | 国产精品毛片久久久久久久 | 中文字幕免费观看全部电影 | 欧美大片大全 | 国产精久久久久久妇女av | 精品久久中文 | 一本一本久久a久久精品综合小说 | 国产va精品免费观看 | 免费久久久久久 | 91精品国产一区 | 成人app在线播放 | 国产精品综合久久久 | 夜夜躁日日躁 | 中文字幕在线观看1 | 亚洲成av人片在线观看 | 亚洲人成在线电影 | 日韩国产欧美在线播放 | 狠狠色伊人亚洲综合成人 | 久久久国产毛片 | 99久久国产免费,99久久国产免费大片 | 日韩黄色软件 | 久草在线费播放视频 | 永久免费观看视频 | 国产亚洲日 | 国产精品伦一区二区三区视频 | 国产又粗又猛又色又黄网站 | 亚洲欧美精品一区二区 | 天天操天天插 | 夜夜嗨av色一区二区不卡 | 日日日爽爽爽 | 在线免费观看黄色大片 | 婷婷网五月天 | 黄色片视频免费 | 国产精品一区二区62 | 青青色影院 | 午夜视频播放 | 黄色免费观看 | 青草视频在线看 | 狠狠色噜噜狠狠狠狠2022 | 国产精品系列在线观看 | 久久久久福利视频 | 黄色小说18| 欧美二区三区91 | 欧美成年人在线观看 | 夜夜夜影院 | 91精品国产乱码久久 | 色就是色综合 | 91在线免费看片 | 国产成人香蕉 | 国产在线999| 国产亚洲精品久久久久久久久久久久 | 国产日韩欧美中文 | 免费精品 | 国产精品免费不 | 激情婷婷 | 午夜色性片| 亚洲激情在线播放 | 色多多视频在线 | 91精品国产九九九久久久亚洲 | 久久第四色 | wwwwwww黄| 国产成人一区二区三区免费看 | 一二三精品视频 | 亚洲高清不卡av | 久久伦理视频 | 国产精品热视频 | 国产精品丝袜 | 国产精选视频 | 在线视频中文字幕一区 | 久久久久久久网站 | 麻豆视频一区 | 伊人伊成久久人综合网小说 | 日本xxxx.com| 97视频入口免费观看 | 免费视频一级片 | 男女日麻批 | 狠狠操在线 | 天天躁天天躁天天躁婷 | 99免费视频 | 五月天久久综合 | 成年人视频在线观看免费 | 成人app在线播放 | 日韩资源在线播放 | a久久久久久 | 日韩av在线看 | 97在线免费视频 | 不卡视频国产 | 免费日韩一区二区三区 | 久久久国产99久久国产一 | 国产黄色片一级三级 | 超碰97成人 | 97在线观看视频 | 黄色小说视频在线 | 欧美精品乱码久久久久久按摩 | 91黄色在线观看 | 日韩在线观看网站 | 久久在线观看视频 | 99久久国产免费看 | 精品国产99国产精品 | 干av在线 | 97在线影院| 91九色porny在线 | 久草资源在线观看 | 麻豆传媒视频观看 | 一区二区三区在线免费观看 | 久久国产精品免费一区 | 在线观看中文字幕视频 | 91精品电影 | 亚洲综合婷婷 | 99这里只有久久精品视频 | 永久免费视频国产 | 97看片吧 | 一区二区三区观看 | 在线免费色 | 成人免费网站在线观看 | 精品一区二区在线观看 | 中文字幕在线观看播放 | 91九色精品女同系列 | 婷婷国产在线观看 | 91麻豆产精品久久久久久 | 国产破处在线视频 | 色一级片 | 国产成人精品一区二三区 | 黄色免费观看 | 久久视频精品在线 | 成人xxxx | 中文字幕影片免费在线观看 | 日韩成人高清在线 | 日日摸日日爽 | 黄色电影小说 | 色婷婷电影 | 亚洲欧美日韩一区二区三区在线观看 | 成人欧美一区二区三区在线观看 | 欧美孕妇视频 | 九九热免费精品视频 | 黄色成人影视 | 国产专区视频在线观看 | 伊人五月天 | 国产在线中文 | 色婷婷综合久久久久中文字幕1 | 97成人在线视频 | www.国产高清| 久久九精品 | 在线日韩亚洲 | 视频国产区 | 国产99精品在线观看 | 国产中文字幕视频在线 | 国产免费观看av | 欧美巨乳波霸 | 97av精品 | 天天干天天操天天做 | 精精国产xxxx视频在线播放 | 国产精品麻豆果冻传媒在线播放 | 中文一区二区三区在线观看 | 成人欧美亚洲 | 欧美一区二区三区在线视频观看 | 高清一区二区 | 日韩在线电影 | 91高清免费 | 97超碰中文字幕 | 在线观看免费黄色 | 日韩免费视频观看 | 中文字幕在线成人 | 国产成人在线看 | 在线观看黄色av | 亚洲人成人99网站 | 国产精品理论片在线观看 | 99久久婷婷国产一区二区三区 | 国产成在线观看免费视频 | 国产精品午夜久久久久久99热 | 曰韩在线| 久久99视频免费 | 黄色在线免费观看网站 | 亚洲欧美国产精品 | 免费看一级片 | 一区二区三区 中文字幕 | 91视频3p | 97超碰精品| 国产精品毛片一区视频播 | 在线视频久| 中文字幕在线观看2018 | 亚洲精品99久久久久久 | 新版资源中文在线观看 | 中文字幕资源站 | 韩国精品视频在线观看 | 人人爽人人澡 | 国产亚洲欧美一区 | 国产手机视频在线播放 | 日韩精品一区二区在线观看 | 在线视频欧美日韩 | 亚洲综合爱 | 日韩精品一区二区三区水蜜桃 | 色婷婷综合成人av | 伊人视频 | 国产高清免费av | 国产中文字幕av | 色干综合 | 九九激情视频 | 在线免费观看视频你懂的 | 色就干| 丁香六月中文字幕 | 欧美成人精品欧美一级乱 | 国产精品一区在线 | 中文欧美字幕免费 | 日韩欧美aaa| 狠狠色丁香九九婷婷综合五月 | 日韩av男人的天堂 | 狠狠综合久久av | 亚洲人成影院在线 | 免费高清在线观看成人 | 亚洲老妇xxxxxx | 国产精品成人av电影 | 手机成人av | 999视频精品 | 韩日三级在线 | 九九爱免费视频 | 国产在线综合视频 | 国产一区二区精品久久 | 超碰人人在线 | 欧美亚洲一区二区在线 | 成人免费观看完整版电影 | 亚洲理论片在线观看 | 亚洲成aⅴ人片久久青草影院 | 久久福利在线 | 久久精品一区二区国产 | 97超碰在线久草超碰在线观看 | 久久99国产一区二区三区 | 日韩理论影院 | 在线观看黄色的网站 | 国产在线视频一区二区三区 | 欧美一区二视频在线免费观看 | 欧美性性网| 亚洲人成综合 | 91av成人 | 99久久精品免费看国产麻豆 | a级一a一级在线观看 | 韩日av一区二区 | 久久字幕网 | 91传媒在线观看 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 亚洲热视频 | 成人黄色在线视频 | 好看的国产精品视频 | 东方av免费在线观看 | 欧洲精品久久久久毛片完整版 | 婷婷久久一区二区三区 | 亚洲精品高清在线 | 精品欧美在线视频 | 蜜桃视频在线视频 | 91av免费看 | 婷婷亚洲五月 | 欧美日韩国产三级 | 国内外成人在线 | 国产又黄又硬又爽 | 精品成人久久 | 日日精品| 日本久久片 | 欧美一级专区免费大片 | 麻豆国产精品一区二区三区 | 国产网红在线观看 | 综合网成人 | 久久精品一区二区三 | 日韩av一区二区三区在线观看 | www五月天| 天天操狠狠操网站 | 欧美日韩精品免费观看 | 久久五月天综合 | 超碰在线成人 | 精品欧美一区二区三区久久久 | 黄色日视频 |