Android Launcher啓動應用程序流程源碼解析

帶着問題看源碼

  1. 點擊桌面Launcher圖標後做了哪些工作?
  2. 應用程序什麼時候被創建的?
  3. Application和MainActivity的onCreate()方法什麼時候被調用的?

概述

在Android系統中,啓動四大組件中的任何一個都可以啓動應用程序。但絕大部分時候我們是通過點擊Launcher圖標啓動應用程序。本文依據Android6.0源碼,從點擊Launcher圖標,直至解析到MainActivity#OnCreate()被調用。

Launcher簡析

Launcher也是個應用程序,不過是個特殊的應用。俗稱“桌面”。通過PackageManagerService查詢所有已安裝的應用程序,並保存相應的圖標、應用名稱、包名和第一個要啓動的類名等。

源碼位置:frameworks/base/core/java/android/app/LauncherActivity.java

LauncherActivity#onListItemClick()

public abstract class LauncherActivity extends ListActivity {
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = intentForPosition(position);
        startActivity(intent);
    }
}

可以看到LauncherActivity繼承自ListActivity,而ListActivity繼承自Activity。在LauncherActivity#onListItemClick()方法中首先通過intentForPosition()獲取了一個Intent,然後調用startActivity(intent)啓動一個Activity。由於ListActivity並沒有重寫Activity#startActivity()方法,所以這裏會直接調用Activity#startActivity()。在此之前先看下intentForPosition()是怎樣構造Intent

    protected Intent intentForPosition(int position) {
        ActivityAdapter adapter = (ActivityAdapter) mAdapter;
        return adapter.intentForPosition(position);
    }

    private class ActivityAdapter extends BaseAdapter implements Filterable {
        public Intent intentForPosition(int position) {
            if (mActivitiesList == null) {
                return null;
            }
            Intent intent = new Intent(mIntent);
            ListItem item = mActivitiesList.get(position);
            intent.setClassName(item.packageName, item.className);
            if (item.extras != null) {
                intent.putExtras(item.extras);
            }
            return intent;
        }
    }

Intent中只是指定了即將啓動的Activity

源碼位置:frameworks/base/core/java/android/app/Activity.java

Activity#startActivity()

    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            startActivityForResult(intent, -1);
        }
    }

    /** @param requestCode If >= 0, this code will be returned inonActivityResult() when the activity exits. */
    public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
            Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
           ...
        }
    }

在調用的過程中可以觀察到,無論調用StartActivity()還是startActivityForResult(),最終調用的都是startActivityForResult()。而且註釋說明只有requestCode >= 0onActivityResult()纔會被調用。經過一系列的調用,最終調用了Instrumentation#execStartActivity()。跟進。

源碼位置:frameworks/base/core/java/android/app/Instrumentation.java

Instrumentation#execStartActivity()

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

這裏ActivityManagerNative.getDefault()涉及到Binder進程間通信機制。下面進行一個簡短的介紹,這不是本文的重點。瞭解過同學的可以略過下面這段Binder簡析,不想了解的也可以直接理解爲返回的是ActivityManagerService(以下簡稱AMS)。實際調用的是AMS#startActivity()

AMS中Binder機制簡析

ActivityManagerNative.getDefault()

    static public IActivityManager getDefault() {
        return gDefault.get();
    }

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            IActivityManager am = asInterface(b);
            return am;
        }
    };

    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

本例中AMS作爲服務器端,ActivityManagerNative作爲客戶端。在getDefault()方法中通過調用asInterface()方法中的 new ActivityManagerProxy(obj)返回了IActivityManager的子類對象AMS。從哪裏可以看出來呢?這個就比較難找了,不過細心點還是可以發現寫蛛絲馬跡。重點在於IBinder b = ServiceManager.getService("activity"),這裏的參數是“activity”。在上篇博文SystemServer啓動流程源碼解析中,分析SystemServer#startBootstrapServices()方法啓動AMS之後調用mActivityManagerService.setSystemProcess(),跟進。

源碼位置:frameworks/base/services/java/com/android/server/SystemServer.java

SystemServer#startBootstrapServices()

    private void startBootstrapServices() {
        Installer installer = mSystemServiceManager.startService(Installer.class);

        // Activity manager runs the show.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        // Set up the Application instance for the system process and get started.
        mActivityManagerService.setSystemProcess();
    }

    public void setSystemProcess() {
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
    }

靜態常量Context.ACTIVITY_SERVICE = "activity"。到這裏就對上了。先addService("activity"),然後getService("activity")。其實在add和get的時候,又是一次通過Binder進行進程間通信的過程。這次和本文關係不大,這裏不再拓展。下面回到AMS#startActivity()

調用過程解析

前方高能,可能會導致身體感到嚴重不適。請做好心理準備!

源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService#startActivity()

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        // 驗證CallingUid是否合法
        enforceNotIsolatedCaller("startActivity");
        // 檢查限權
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

簡單驗證後開始調用StackSupervisor#startActivityMayWait(),跟進。
源碼位置:frameworks/base/services/core/java/com/android/server/am/StackSupervisor.java

StackSupervisor#startActivityMayWait()、StackSupervisor#resolveActivity()

    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, WaitResult outResult, Configuration config,
                                   Bundle options, boolean ignoreTargetSecurity, int userId,
                                   IActivityContainer iContainer, TaskRecord inTask) {
          ...
         // 解析intent信息                         
         ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
         // 驗證pid uid(省略)
         ...
        int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                voiceSession, voiceInteractor, resultTo, resultWho,
                requestCode, callingPid, callingUid, callingPackage,
                realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                componentSpecified, null, container, inTask);

        return res;                          
    }

    ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
                                 ProfilerInfo profilerInfo, int userId) {
        // Collect information about the target of the Intent.
        ActivityInfo aInfo;
        try {
            ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent(
                            intent, resolvedType,
                            PackageManager.MATCH_DEFAULT_ONLY 
                            | ActivityManagerService.STOCK_PM_FLAGS, userId);
            aInfo = rInfo != null ? rInfo.activityInfo : null;
        } catch (RemoteException e) {
            aInfo = null;
        }

        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
            ...
        }
        return aInfo;
    }

在調用resolveActivity()之後會讀取配置文件中包名和要啓動Activity完整的路徑名,並分別賦值給aInfo.applicationInfo.packageName和aInfo.name。跟進。

StackSupervisor#startActivityLocked()

    final int startActivityLocked(IApplicationThread caller,
                                  Intent intent, String resolvedType, ActivityInfo aInfo,
                                  IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                                  IBinder resultTo, String resultWho, int requestCode,
                                  int callingPid, int callingUid, String callingPackage,
                                  int realCallingPid, int realCallingUid, int startFlags, Bundle options,
                                  boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
                                  ActivityContainer container, TaskRecord inTask) {
        ProcessRecord callerApp = null;
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {
                err = ActivityManager.START_PERMISSION_DENIED;
            }
        }
        ...
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, voiceSession != null, this, container, options);
        // 檢查intent中的flag信息
        ...
        // 檢查限權
        ...
        ...
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);
        return err;

    }

這個方法近300行代碼,我們只看關鍵的部分就好了。首先獲取調用者的pid、uid等信息,然後保存在callerApp中。目標Activity的信息保存在 r 中。跟進。

StackSupervisor#startActivityUncheckedLocked()

    final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
        boolean doResume, Bundle options, TaskRecord inTask) {
        ...
        int launchFlags = intent.getFlags();
        // 對intent的flag各種判斷
        ...
        ActivityRecord notTop = (launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
        ...
                ActivityStack sourceStack;
        if (sourceRecord != null) {
            if (sourceRecord.finishing) {
                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                    Slog.w(TAG, "startActivity called from finishing " + sourceRecord
                            + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
                    newTaskInfo = sourceRecord.info;
                    newTaskIntent = sourceRecord.task.intent;
                }
                sourceRecord = null;
                sourceStack = null;
            } else {
                sourceStack = sourceRecord.task.stack;
            }
        } else {
            sourceStack = null;
        }
        ...
        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || launchSingleInstance || launchSingleTask) {
            if (inTask == null && r.resultTo == null) {
                // See if there is a task to bring to the front.  If this is
                // a SINGLE_INSTANCE activity, there can be one and only one
                // instance of it in the history, and it is always in its own
                // unique task, so we do a special search.
                ActivityRecord intentActivity = !launchSingleInstance ?
                        findTaskLocked(r) : findActivityLocked(intent, r.info);
        ...
        }
        ...
        // Should this be considered a new task?
        if (r.resultTo == null && inTask == null && !addingToTask
                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            targetStack = computeStackFocus(r, newTask);
            targetStack.moveToFront("startingNewTask");

            if (reuseTask == null) {
                // 設任務棧
                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                        newTaskInfo != null ? newTaskInfo : r.info,
                        newTaskIntent != null ? newTaskIntent : intent,
                        voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
                        taskToAffiliate);
            } 
            ...
        }
        ...
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        return ActivityManager.START_SUCCESS;
    }

這個方法600+行,而且好多邏輯判斷,看的幾近崩潰。不過還好,關鍵的代碼已經被過濾出來了~首先確定幾個變量。前面都沒有設置過intentflag,所以launchFlags = 0x00000000,但是在執行launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK之後。launchFlags = Intent.FLAG_ACTIVITY_NEW_TASKnotTop = null。由於沒有要接收返回信息的Activity,所以r.resultTo == null。由於沒有設置Activity的啓動模式爲SingleInstance,所以launchSingleInstance = false,即會執行findTaskLocked(r)。這個方法的作用是查找歷史所有stack中有沒有目標Activity,很顯然返回值爲null,所以下面很大一段判斷邏輯都不會執行。大約200行,爽~。既然沒有相應的任務棧,肯定要創建的。在上文中創建任務棧對應的方法爲targetStack.createTaskRecord()。最後執行ActivityStack#startActivityLocked(),跟進。

源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

ActivityStack#startActivityLocked()

    final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        ...
        // newTask = true
        if(!newTask){
            ...
        }
        task = r.task;
        // 將ActivityRecord置於棧頂
        task.addActivityToTop(r);
        // 將任務棧置於前臺
        task.setFrontOfTask();
        ...
        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

跟進。

源碼位置:frameworks/base/services/core/java/com/android/server/am/StackSupervisor.java

StackSupervisor#resumeTopActivitiesLocked()

    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
                                      Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = mFocusedStack;
        }
        // Do targetStack first.
        boolean result = false;
        if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (stack == targetStack) {
                    // Already started above.
                    continue;
                }
                if (isFrontStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }

這個方法的作用是將Launcher應用程序所在的任務棧執行resumeTopActivityLocked()方法。跟進。

源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

ActivityStack#resumeTopActivityLocked()

    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }

跟進。

ActivityStack#resumeTopActivityInnerLocked()

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
        ...
        // If the top activity is the resumed one, nothing to do.
        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                    mStackSupervisor.allResumedActivitiesComplete()) {
            ...
            return false;
        }
        ...
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
        }
        ...
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
        ...
    }

這個方法的主要作用是將mResumedActivity暫停(Launcher任務棧的TopActivity),即進入onPause狀態。之後啓動指定的AttivityRecored,即target AttivityRecored

源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

ActivityStackSupervisor#startSpecificActivityLocked()

    void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags & ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    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);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

由於沒有在指定Applicationprocess屬性,所以這裏的app = null

詳見ActivityStackSupervisor#getProcessRecordLocked()

    final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
        if (uid == Process.SYSTEM_UID) {
            // The system gets to run in any process.  If there are multiple
            // processes with the same uid, just pick the first (this
            // should never happen).
            SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(processName);
            if (procs == null) return null;
            ...
        }
        ...
    }

跟進。

源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

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 */);
    }

跟進。

ActivityManagerService#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) {
        // isolated = false
        if (!isolated) {
            // 沒有指定application的process,所以app = null
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            ...
        }
        ...
        if (app == null) {
            checkTime(startTime, "startProcess: creating new process record");
            // 創建ProcessRecord
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
            ...
            checkTime(startTime, "startProcess: done creating new process record");
        }
    }
        ...
        checkTime(startTime, "startProcess: stepping in to startProcess");
        // hostingNameStr="activity" 後面仨參數都是null
        startProcessLocked(
                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        checkTime(startTime, "startProcess: done starting proc!");

終於看見Process的身影了,親人吶!!!

ActivityManagerService#startProcessLocked()

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            ...
        try {
            int uid = app.uid;
            int[] gids = null;
            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
            // isolated = false
            if (!app.isolated) {
                int[] permGids = null;
                try {
                    checkTime(startTime, "startProcess: getting gids from package manager");
                    final IPackageManager pm = AppGlobals.getPackageManager();
                    permGids = pm.getPackageGids(app.info.packageName, app.userId);
                    MountServiceInternal mountServiceInternal = LocalServices.getService(
                            MountServiceInternal.class);
                    mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
                            app.info.packageName);
                } catch (RemoteException e) {
                    throw e.rethrowAsRuntimeException();
                }

                /*
                 * Add shared application and profile GIDs so applications can share some
                 * resources like shared libraries and access user-wide resources
                 */
                if (ArrayUtils.isEmpty(permGids)) {
                    gids = new int[2];
                } else {
                    gids = new int[permGids.length + 2];
                    System.arraycopy(permGids, 0, gids, 2, permGids.length);
                }
                gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
                gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
            }
            ...
            String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
            if (requiredAbi == null) {
                requiredAbi = Build.SUPPORTED_ABIS[0];
            }

            String instructionSet = null;
            if (app.info.primaryCpuAbi != null) {
                instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
            }

            app.gids = gids;
            app.requiredAbi = requiredAbi;
            app.instructionSet = instructionSet;

            checkTime(startTime, "startProcess: asking zygote to start proc");
            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);
            checkTime(startTime, "startProcess: returned from zygote!");
            ...
        }
        ...
    }

這個方法太重要了,所以展示的代碼稍微多一些。首先確定幾個參數值。hostingType = activity、後面的三個參數abiOverrideentryPointentryPointArgs均等於nullapp.isolated = false。首先創建了gids[]這個參數,然後在前兩項插入AppGidUserGid,然後構造了requiredAbiinstructionSet等參數,之後調用Process#start()來創建新進程。Process#start()。現在是凌晨兩點,如果你像我一樣已經寫了5個小時,一定會發現這方法名字是多麼的讓人陶醉~

抽只煙冷靜下~

跟進。

源碼位置:frameworks/base/core/java/android/os/Process.java

Process#start()

    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 {
            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);
        }
    }

這是隻是調用startViaZygote()進一步處理。跟進。

Process#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) {
            ArrayList<String> argsForZygote = new ArrayList<String>();

            // --runtime-args, --setuid=, --setgid=,
            // and --setgroups= must go first
            argsForZygote.add("--runtime-args");
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
            ...
                        // --setgroups is a comma-separated list
            if (gids != null && gids.length > 0) {
                StringBuilder sb = new StringBuilder();
                sb.append("--setgroups=");

                int sz = gids.length;
                for (int i = 0; i < sz; i++) {
                    if (i != 0) {
                        sb.append(',');
                    }
                    sb.append(gids[i]);
                }

                argsForZygote.add(sb.toString());
            }

            if (niceName != null) {
                argsForZygote.add("--nice-name=" + niceName);
            }

            if (seInfo != null) {
                argsForZygote.add("--seinfo=" + seInfo);
            }

            if (instructionSet != null) {
                argsForZygote.add("--instruction-set=" + instructionSet);
            }

            if (appDataDir != null) {
                argsForZygote.add("--app-data-dir=" + appDataDir);
            }

            argsForZygote.add(processClass);

            if (extraArgs != null) {
                for (String arg : extraArgs) {
                    argsForZygote.add(arg);
                }
            }
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

可以看到,這裏前面一大段都在構造參數argsForZygoteuid啦、gid啦、-nice-name啦,這裏需要注意processClass = android.app.ActivityThread,後文會用到。參數構造完成之後,接下來看下openZygoteSocketIfNeeded()這個方法。

Process#openZygoteSocketIfNeeded()

    /**
     * Tries to open socket to Zygote process if not already open. If
     * already open, does nothing.  May block and retry.
     */
    private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
                primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
            }
        }

        if (primaryZygoteState.matches(abi)) {
            return primaryZygoteState;
        }

        // The primary zygote didn't match. Try the secondary.
        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
            try {
            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);
    }

罕見的我把註釋寫上了,因爲註釋說的比我清楚~接下來跟進zygoteSendArgsAndGetResult()方法。

Process#zygoteSendArgsAndGetResult()

    /**
     * Sends an argument list to the zygote process, which starts a new child
     * and returns the child's pid. Please note: the present implementation
     * replaces newlines in the argument list with spaces.
     *
     * @throws ZygoteStartFailedEx if process start failed for any reason
     */
    private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            /**
             * See com.android.internal.os.ZygoteInit.readArgumentList()
             * Presently the wire format to the zygote process is:
             * a) a count of arguments (argc, in essence)
             * b) a number of newline-separated argument strings equal to count
             *
             * After the zygote process reads these it will write the pid of
             * the child or -1 on failure, followed by boolean to
             * indicate whether a wrapper process was used.
             */
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;

            writer.write(Integer.toString(args.size()));
            writer.newLine();

            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                if (arg.indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx(
                            "embedded newlines not allowed");
                }
                writer.write(arg);
                writer.newLine();
            }

            writer.flush();

            // Should there be a timeout on this?
            ProcessStartResult result = new ProcessStartResult();
            result.pid = inputStream.readInt();
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = inputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }

註釋也說的很清楚,給Zygote發送一個argument list。通知Zygote進程啓動一個子進程。再接下來就該和Zygote進程打交道了。

太晚了,關鍵明天還要上班。明天再細緻分析這部分,古耐~

大哥大Zygote

在另一篇博文 Android Zygote啓動流程源碼解析中說到:在Zygote#main()中先註冊了一個serverSocket,在啓動了SystemServer進程之後,一直監聽這個serverSocket,準備啓動新的應用進程。大概過程如下:

源碼位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

ZygoteInit#main()

public static void main(String argv[]) {
    // 註冊socket
    registerZygoteSocket(socketName);
    ...
    if (startSystemServer) {
        // 啓動SystemServer進程
        startSystemServer(abiList, socketName);
    }
    // 監聽socket,啓動新的應用進程。--後文會講
    runSelectLoop(abiList);
    closeServerSocket();
    ...
}

跟進runSelectLoop(abiList)

ZygoteInit#runSelectLoop()

    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        while (true) {
            int index;
            ...
            if (index < 0) {
                throw new RuntimeException("Error in select()");
            } else if (index == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDescriptor());
            } else {
                boolean done;
                done = peers.get(index).runOnce();

                if (done) {
                    peers.remove(index);
                    fds.remove(index);
                }
            }
        }   
    }

    private static ZygoteConnection acceptCommandPeer(String abiList) {
        try {
            return new ZygoteConnection(sServerSocket.accept(), abiList);
        } catch (IOException ex) {
            ...
        }
    }

這個方法的主要作用是通過acceptCommandPeer()方法接收客戶端發送的Socket消息。之後執行ZygoteConnection#runOnce()方法。跟進。

源碼位置:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

ZygoteConnection#runOnce()

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        ...
        checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);
        checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
        ...
        if (pid == 0) {
            // in child
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
                // should never get here, the child is expected to either
                // throw ZygoteInit.MethodAndArgsCaller or exec().
                return true;
            } else {
               ...
            }
            ...
    }

省略的一大段代碼都在構造參數,之後根據參數調用Zygote.forkAndSpecialize()方法fork出應用程序進程,到這裏,應用進程已經被創建了。因爲是子進程pid = 0,所以之後會調用handleChildProc()方法進一步處理。跟進。

ZygoteConnection#handleChildProc()

    private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
        closeSocket();
        ZygoteInit.closeServerSocket();
        ...
        ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
        ...
    }   

上述代碼先關閉從Zygote進程繼承來的ServerSocket,然後調用ZygoteInit.invokeStaticMain()。接下來的流程和啓動System進程流程差不多,這裏快速的過一遍。不熟悉這部分的同學可以參考這篇博客

源碼位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

ZygoteInit#invokeStaticMain()

    static void invokeStaticMain(ClassLoader loader, String className, String[] argv)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;
        try {
            cl = loader.loadClass(className);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className, ex);
        }
        Method m;
        m = cl.getMethod("main", new Class[] { String[].class });
        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

意料之中的裝載類文件、意料之中的反射、意料之中的驗證修飾符、意料之中的拋出個異常,甚至意料之中的在Zygote#main()中捕獲。看過Zygote啓動流程源碼解析的讀着肯定和我有一樣的感覺。接下來就該捕獲異常,然後反射ActivityThread的靜態方法main()。直接貼代碼了,so boring…

ZygoteInit#main()

    public static void main(String argv[]) {
        try {
            ...
            runSelectLoop(abiList);
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        }

        // ZygoteInit&MethodAndArgsCaller#run()
        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                ...
            } 
        }

這裏反射調用的是ActivityThread#main()方法。跟進。

主進程的創建流程

源碼位置:frameworks/base/core/java/com/android/app/ActivityThread.java

ActivityThread#main()

    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();
        ...
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

我們知道ActivityThread就是所謂的主線程,其實ActivityThread並不是一個主線程。只是一個擁有mainLooper的入口方法。

概述中說:在Android系統中,啓動四大組件中的任何一個都可以啓動應用程序。啓動四大組件的都可以啓動應用程序,但實際上入口方法只有ActivityThread#main()一個(未驗證)。

在做了一些初始化的工作後,調用了ActivityThread#attach(false)。跟進。

    final ApplicationThread mAppThread = new ApplicationThread();

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ...
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            ...
        }
        ...
    }

前文AMS中的Binder機制中分析過:ActivityManagerNative.getDefault(),返回的是AMS。其中跟進。

源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

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);
        }
    }

這裏只是調用兩個參數的attachApplicationLocked()方法處理。跟進。

    private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
        ...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
        ...
    }

跟進。

源碼位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

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;
                }
                ActivityRecord hr = stack.topRunningActivityLocked(null);
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                            if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            ...
                        }
                    }
                }
            }
        }
        ...
        return didSomething;
    }

首先遍歷所有stack,之後找到目前被置於前臺的stack。之後通過topRunningActivityLocked()獲取最上面的Activity。最後調用realStartActivityLocked()方法來真正的啓動目標Activity。跟進

源碼位置:frameworks/base/services/java/com/android/server/am/ActivityStack.java

ActivityStack#realStartActivityLocked()

    final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
        ...
                    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
                    r.icicle, r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);
    }
    ...

這裏通過Binder,會調用ApplicationThread#scheduleLaunchActivity()。跟進。

源碼位置:frameworks/base/core/java/android/app/ActivityThread.java

ActivityThread&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();
            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            ...
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

構造一個ActivityClientRecord對象之後,調用sendMessage(H.LAUNCH_ACTIVITY, r)。跟進。

    private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

根據參數組裝了一個Message對象,之後通過mH.sendMessage(msg)發送出去。看下mH是個什麼鬼。跟進。

ActivityThread、ActivityThread&H

public final class ActivityThread {
    ...
    final H mH = new H();
    ...
        private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        ...
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                ...
            }
        }
    }
}

原來mH不過是Handler的子類罷了。接着在handleMessage()中解析出Message對象,然後調用handleLaunchActivity()進一步處理。跟進。

ActivityThread#handleLaunchActivity()

    private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
        ......  
        // 加載activity,然後調用onCreate,onStart方法
        Activity a = performLaunchActivity(r, customIntent);  
        if (a != null) {
            // 調用onResume方法
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
            ...   
        }
        ... 
    }  

這是個蠻重要的方法。Activity啓動流程源碼解析裏有詳細講解,這裏暫時略過。
跟進。

ActivityThread#performLaunchActivity()

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                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()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }

        return activity;
    }

因爲這個方法比較重要,所以代碼完整的貼出來了。可以看到,首先收集要啓動的Activity信息。然後通過ClassLoader加載目標Activiy類。再然後創建Application,最後調用Activity#onCreate()。內容有些多,我們一步步的看。先從創建Application說起。r.packageInfoLoadedApk對象,所以會調用LoadedApk#makeApplication()

源碼位置:frameworks/base/core/java/android/app/LoadedApk.java

LoadedApk#makeApplication()

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Application app = null;
        ...
        try {
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
        } catch (Exception e) {
            ...
        }
        ...
        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                ...
                }
            }
        }
        return app;
    }

方法名稱已經很明顯了。跟進。

源碼位置:frameworks/base/core/java/android/app/Instrumentation.java

Instrumentation#newApplication()

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        return newApplication(cl.loadClass(className), context);
    }

    static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }

簡單粗暴,通過反射創建一個Application實例。現在實例有了,但onCreate()方法還沒有被調用。跟進Instrumentation#callApplicationOnCreate()

    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }

這都沒法解析了,,直接調用Application#onCreate()。現在已經有了Application,但Activity只是被ClassLoader裝載了,onCreate()還沒有調起來。回到ActivityThread#performLaunchActivity()

        ...
        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);

        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        ...

跟進。

源碼位置:frameworks/base/core/java/android/app/callActivityOnCreate.java

Instrumentation#callActivityOnCreate()

    public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }

    // Activity#performCreate()
    final void performCreate(Bundle icicle) {
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

Activity#performCreate()這裏調用了OnCreate()方法。終於把我們的應用程序啓動起來了~

總結

總體流程

  1. Launcher通過Binder機制通知AMS啓動一個Activity
  2. AMS使Launcher棧最頂端Activity進入onPause狀態
  3. AMS通知Process使用Socket和Zygote進程通信,請求創建一個新進程
  4. Zygote收到Socket請求,fork出一個進程,並調用ActivityThread#main()
  5. ActivityThread通過Binder通知AMS啓動應用程序
  6. AMS通知ActivityStackSupervisor真正的啓動Activity
  7. ActivityStackSupervisor通知ApplicationThread啓動Activity
  8. ApplicationThread發消息給ActivityThread,需要啓動一個Activity
  9. ActivityThread收到消息之後,通知LoadedApk創建Applicaition,並且調用其onCteate()方法
  10. ActivityThread裝載目標Activity類,並調用Activity#attach()
  11. ActivityThread通知Instrumentation調用Activity#onCreate()
  12. Instrumentation調用Activity#performCreate(),在Activity#performCreate()中調用自身onCreate()方法

第一次啓動應用程序,Application和Activity#onCreate()方法調用順序

  1. 裝載Activity
  2. 裝載Application
  3. Application#attach()
  4. Application#onCreate()
  5. Activity#attach()
  6. Activity#onCreate()


更多Framework源碼解析,請移步 Framework源碼解析系列[目錄]

發佈了56 篇原創文章 · 獲贊 213 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章