App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析

guanpj發表於2019-01-24

在我的上一篇文章Android 系統啟動流程分析中,我們分析了系統在開機以後的一系列行為,其中最後一階段 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 所在的程式中發生的,在我的另外一篇文章藉助 AIDL 理解 Android Binder 機制——AIDL 的使用和原理分析中我們分析了 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;
    }
};
複製程式碼

同樣,在文章藉助 AIDL 理解 Android Binder 機制——Binder 來龍去脈中也講到過:

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_TRANSACTION
        mRemote.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 的時序圖如下:

Launcher2AMS

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 附屬的 Application
    ProcessRecord 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 開始的呼叫時序圖如下:

AMS2Zygote

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 Exception
        implements Runnable {
        
    private final Method mMethod;
    private final String[] mArgs;
        
    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }
    public void run() {
        try {
            // 呼叫傳遞過來的 mMethod
            mMethod.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>");
    // 建立主執行緒 Looper
    Looper.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 程式的過程如出一轍,時序圖如下所示:

Zygote2ActivityThread

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 {
        ...
        // 獲取應用appInfo
        ApplicationInfo 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) { 
        // 殺掉 badApp
        app.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, boolean
    enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configuration
    config, 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 方法建立 Application
        Application 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 狀態的 Activity
            ActivityRecord hr = stack.topRunningActivityLocked(null);
            if (hr != null) {
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid && processName.equals(hr.processName)) {
                    try {
                        // 真正的啟動 Activity
                        if (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) {
            // 第二次啟動失敗,則結束該 Activity
            mService.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) {
    ...
    // 初始化 WMS
    WindowManagerGlobal.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 {
        // 停止該 Activity
        ActivityManagerNative.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 中使用反射建立 Activity
        activity = 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()) {
                // 重新建立的 Activity
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                // 第一次建立的 Activity
                mInstrumentation.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 方法,整個過程的時序圖如下:

ActivityThread2Activity

5. 總結

縱觀整個過程,從 Launcher 到 AMS、從 AMS 再到 Zygote、再從 Zygote 到 ActivityThread,最後在 ActivitThread 中層層呼叫到 Activity 的生命週期方法,中間涉及到了無數的細節,但總體上脈絡還是非常清晰的,各個 Android 版本的 Framework 層程式碼可以某些過程的實現不太一樣,但是整個呼叫流程大體上也是相同的,借用 Gityuan 大神的一張圖作為結尾:

Activity_Start_Process

系列文章

按下電源鍵後竟然發生了這一幕 —— Android 系統啟動流程分析

App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析(本文)

螢幕上內容究竟是怎樣畫出來的 —— Android View 工作原理詳解

參考文章

startActivity啟動過程分析

Android深入四大元件(一)應用程式啟動過程(前篇)

如果你對文章內容有疑問或者有不同的意見,歡迎留言,我們一同探討。

相關文章