Activity的啓動流程分析與總結

參考文獻:劉望舒《Android進階解密》

前言

​ 看了數片分析Activity啓動流程的文章,但是自從看了《Android進階解密》關於Activity啓動流程的分析,我就放棄了自己擼一遍的念頭。因爲書裏關於這部分的分析比較詳細。這裏記錄一下書中關於Activity的啓動流程。加深一下印象,便於以後溫習查看。
Activity的啓動過程分爲兩種,一種是根Activity的啓動過程,可以認爲是初次點擊桌面的應用圖標,啓動Manifest中註冊的作爲應用的啓動頁面的Activity。根Activity的啓動過程也可以理解爲應用程序的啓動過程。另一種就是普通Activity的啓動過程,也就是根Activity以外的Activity的啓動過程。這兩種Activity的啓動過程有重疊的部分,但是根Activity一般理解爲應用程序的啓動過程,更具有指導意義。因此本文就根Activity的啓動過程進行分析。

談到Activity的啓動流程就繞不開ActivityManagerService(簡稱AMS),它主要負責四大組件的啓動、切換、調度以及進程的管理,是Android中最核心的服務,參與了所有應用程序的啓動管理。Activity的啓動流程圍繞AMS,可以大致分爲3個部分:

  • Launcher請求AMS的過程
  • AMS到ApplicationThread的調用過程
  • ActivityThread啓動Activity的過程

下面就針對這3個部分逐一進行分析。

1.Launcher請求AMS的過程

該過程的時序圖如下:

在這裏插入圖片描述
當我們點擊桌面的應用快捷圖標時,就會調用Launcher的startActivitySafely方法:

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
    ...
    // Prepare intent
    // 註釋1
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    ...
            // Could be launching some bookkeeping activity
        	// 註釋2
            startActivity(intent, optsBundle);
    ...
}

對於不太需要關注的代碼省略了,主要是走調用流程,對關鍵代碼進行分析,在註釋1處將Flag設置爲Intent.FLAG_ACTIVITY_NEW_TASK,這樣根Activity會在新的任務棧中啓動。在註釋2處調用startActivity方法,這個方法在Activity中實現,Activity中startActivity方法有好幾種重載方式,但它們最終都會調用startActivityForResult方法:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
    	// 註釋1
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            // 註釋2
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            ...
        } else {
            ...
        }
    }

註釋1處的mParent是Activity類型的,表示當前Activity的父類,因爲目前根Activity還沒有創建出來,因此mParent==null成立,執行註釋2處的邏輯,調用Instrumentation的execStartActivity方法,Instrumentation主要是用來監控應用程序和系統的交互,execStartActivity方法代碼如下:

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            // 註釋1
            int result = ActivityManager.getService()
                .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的代碼,首先調用ActivityManager的getService方法來獲取AMS的代理對象,接着調用startActivity方法。我們先進入ActivityManager的getService方法:

public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
        	@Override
            protected IActivityManager create() {
                // 註釋1
            	final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                // 註釋2
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
 		};

getService方法調用了IActivityManagerSingleton的get方法,看一下Singleton代碼

public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

不難發現IActivityManagerSingleton的get方法,會調用create方法,在註釋1處得到IBinder類型的AMS引用,接着在註釋2處將它轉化成IActivityManager類型的對象,即AMS的代理對象,這段代碼採用的是AIDL,IActivityManager.java類是由AIDL工具在編譯時自動生成的。AMS繼承IActivityManager.Stub類並實現相關方法。通過這個代理對象和AMS(AMS所在的進程爲SystemServer系統服務進程)進行跨進程通信,如果你對Binder機制有一定的認識,這裏就比較好理解。如果還不太熟悉Binder機制,強烈建議一定要補一下,要不然分析源碼總會一知半解的。需要注意的Android8.0之前並沒有採用AIDL,是用AMS的代理對象ActivityManagerProxy來與AMS進行跨進程通信的。Android8.0去除了ActivityManagerNative的內部類ActivityManagerProxy,代替它的是IActivityManager,它就是AMS的代理對象。經過上面的分析,我們知道execActivity方法最終調用的是AMS的startActivity方法。補充一句,這裏就由Launcher進程經過一系列調用到了SystemServer進程,可以簡單概括爲下圖:

在這裏插入圖片描述

2.AMS到ApplicationThread的調用過程

Launcher請求AMS後,代碼邏輯進入AMS中,接着是AMS到ApplicationThread的調用流程,時序圖如下:
在這裏插入圖片描述

AMS的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 bOptions) {
	return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

AMS的startActivity方法中返回了startActivityAsUser方法,可以發現startActivityAsUser方法比startActivity方法多了一個參數UserHandle.getCallingUserId(),這個方法會獲得調用者的UserId,AMS根據這個UserId來確定調用者的權限。下面進入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) {
    // 註釋1
    // 判斷調用者進程是否被隔離
    enforceNotIsolatedCaller("startActivity");
    // 註釋2
    // 檢查調用者的權限
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(),
             Binder.getCallingUid(),userId, false, ALLOW_FULL_ONLY, 
             "startActivity", null);
    // TODO: Switch to user app stacks here.
	return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
	       resolvedType, null,null, resultTo, resultWho,requestCode,startFlags,
	       profilerInfo,null,null, bOptions, false, userId, null,
	       null,"startActivityAsUser");
}

在註釋1處判讀調用者進程是否隔離,如果沒被隔離則拋出SecurityException異常,在註釋2處檢查調用者是否有權限,如果沒有權限也會拋出SecurityException異常。最後調用了ActivityStarter的startActivityMayWait方法,參數要比startActivityAsUser多幾個,需要注意的是倒數第二個參數類型爲TaskRecord,代表啓動的Activity所在的棧,最後一個參數"startActivityAsUser"代表啓動的理由,接下來進入startActivityMayWait方法:

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 globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, 	
            int userId,IActivityContainer iContainer, TaskRecord inTask, String reason) {
	...
    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, reason);
        ...
        return res;
     }
}

ActivityStarter是Android7.0中新加入的類,它是加載Activity的控制類,會收集所有的邏輯來決定如何將Intent和Flags轉換爲Activity,並將Activity和Task以及Stack相關聯。ActivityStarter的startActivityMayWait方法調用了startActivityLocked方法:

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, String reason) {
	// 註釋1
    // 判斷啓動
    if (TextUtils.isEmpty(reason)) {
    	throw new IllegalArgumentException("Need to specify a reason.");
    }
    ...
    mLastStartReason = reason;
    mLastStartActivityTimeMs = System.currentTimeMillis();
    mLastStartActivityRecord[0] = null;
	// 註釋2
    mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, 
    			resolvedType,aInfo, rInfo, voiceSession, voiceInteractor, resultTo,
    			resultWho, requestCode,callingPid, callingUid, callingPackage, 
    	        realCallingPid,realCallingUid,startFlags,options,ignoreTargetSecurity,
    	        componentSpecified,mLastStartActivityRecord,container, inTask);
    if (outActivity != null) {
        // mLastStartActivityRecord[0] is set in the call to startActivity above.
        outActivity[0] = mLastStartActivityRecord[0];
    }
    return mLastStartActivityResult;
}

在註釋1處判斷啓動的理由不爲空,如果爲空則拋出IllegalArgumentException異常。緊接着在註釋2處又調用了startActivity方法:

/** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
private int startActivity(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) {
    
    int err = ActivityManager.START_SUCCESS;
    // Pull the optional Ephemeral Installer-only bundle out of the options early.
    final Bundle verificationBundle
    	= options != null ? options.popAppVerificationBundle() : null;

    ProcessRecord callerApp = null;
    // 註釋1
    // caller爲IApplicationThread類型
    if (caller != null) {
        // 註釋2
        // 得到Launcher進程
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) {
            // 獲取Launcher進程的pid和uid
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        } else {
            Slog.w(TAG, "Unable to find app for caller " + caller
                   + " (pid=" + callingPid + ") when starting: "
                   + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }
    ...
    // 註釋3
    // 創建即將要啓動的Activity的描述類ActivityRecord
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
    	callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
        resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
        mSupervisor, container, options, sourceRecord);
    if (outActivity != null) {
        // 註釋4
        outActivity[0] = r;
    }
    ...
    doPendingActivityLaunchesLocked(false);
    // 註釋5
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
    true,options, inTask, outActivity);
    }

ActivityStarter的startActivity方法邏輯比較多,這裏列出部分需要注意的代碼。在註釋1處判斷IApplicationThread類型的caller是否爲null,這個caller是方法調用一路傳過來的,指向的是Launcher所在的應用程序進程的ApplicationThread對象,在註釋2處調用AMS的getRecordForAppLocked方法得到的是代表Launcher進程的callApp對象,它是ProcessRecord類型的,ProcessRecord用於描述一個應用程序進程。同樣的,ActivityRecord用於描述一個Activity,用來記錄一個Activity的所有信息。接下來創建ActivityRecord,用於描述將要啓動的Activity,並在註釋4處將創建的ActivityRecord賦值給ActivityRecord[]類型的outActivity,這個outActivity會作爲註釋5處的startActivity方法的參數傳遞下去。

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
	IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
    ActivityRecord[] outActivity) {
    
    int result = START_CANCELED;
    try {
    	mService.mWindowManager.deferSurfaceLayout();
        // 註釋1
        result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
             startFlags, doResume, options, inTask, outActivity);
    } 
    ...
    return result;
}

startActivity方法接着調用了startActivityUnchecked方法:

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {

        ...
        // 註釋1
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            // 註釋2
            // 創建新的TaskRecord
            result = setTaskFromReuseOrCreateNewTask(
                    taskToAffiliate, preferredLaunchStackId, topStack);
        } else if (mSourceRecord != null) {
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
            result = setTaskFromInTask();
        } else {
            // This not being started from an existing activity, 
            // and not part of a new task...
            // just put it in the top task, though these days this case should never happen.
            setTaskToCurrentTopOrCreateNewTask();
        }
    	...
            
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
 			...
            } else {
                if (mTargetStack.isFocusable()&&!mSupervisor.isFocusedStack(mTargetStack)) {
                    	mTargetStack.moveToFront("startActivityUnchecked");
                }
                // 註釋3
              mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack,mStartActivity,
              			  mOptions);
            }
        } else {
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        ...
    }

startActivityUnchecked方法主要處理與棧管理相關的邏輯。在前面Launcher的startActivitySafely中,將Intent的Flag設置爲FLAG_ACTIVITY_NEW_TASK,這樣註釋1處的條件判斷就會滿足,接着執行註釋2處的setTaskFromReuseOrCreateNewTask方法內部會創建一個新的Activity任務棧。在註釋3處會調用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法:

boolean resumeFocusedStackTopActivityLocked(
    	ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions){
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    // 註釋1
    // 獲取要啓動的Activity所在的棧的棧頂的不是處於停止狀態的ActivityRecord
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    // 註釋2
    if (r == null || r.state != RESUMED) {
        // 註釋3
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    } else if (r.state == RESUMED) {
        // Kick off any lingering app transitions form the MoveTaskToFront operation.
        mFocusedStack.executeAppTransition(targetOptions);
    }
    return false;
}

註釋1處調用ActivityStack的topRunningActivityLocked方法獲取要啓動的Activity所在棧的棧頂並且不是停止狀態的ActivityRecord。在註釋2處,如果ActivityRecord不爲null,或者要啓動的Activity的狀態不是RESUMED狀態,就會調用註釋3處的ActivityStack的resumeTopActivityUncheckedLocked方法,對於即將啓動的Activity,註釋2處條件判斷是肯定滿足的,接下來查看ActivityStack的resumeTopActivityUnchecked方法:

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

    boolean result = false;
    try {
        // Protect against recursion.
        mStackSupervisor.inResumeTopActivity = true;
        // 註釋1
        result = resumeTopActivityInnerLocked(prev, options);
    } 
    ...
}

緊接着查看註釋1處的ActivityStack的resumeTopActivityInnerLocked方法:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { 
    ...
        	// 註釋1
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }

接着進入註釋1處,ActivityStackSupervisor的startSpecificActivityLocked方法

void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    // 註釋1
    // 獲取即將啓動的Activity的所在的應用進程
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                        r.info.applicationInfo.uid, true);

    r.getStack().setLaunchTime(r);
	// 註釋2
    // 判斷要啓動的Activity所在的應用程序進程如果已經運行的話,就會調用註釋3處
    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);
                }
                // 註釋3
                // 這個方法第二個參數是代表要啓動的Activity所在的應用程序進程的ProcessRecord
                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);
    }

​ 在註釋1處獲取即將啓動的Activity所在的應用程序進程,在註釋2處判斷要啓動的Activity所在的應用程序進程如果已經運行的話,就會調用註釋3處的realStartActivityLocked方法,這個方法的第二個參數是代表要啓動的Activity所在的應用程序進程的ProcessRecord。接下來進入realStartActivityLocked方法:

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
      boolean andResume, boolean checkConfig) throws RemoteException {
    ...
    // 註釋1
    // app是ProcessRecord類型的,thread是IApplicationThread類型的 
	app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
    	System.identityHashCode(r), r.info,
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, !andResume,
        mService.isNextTransitionForward(), profilerInfo);
        ...
        return true;
}

​ 註釋1處的app.thread指的是IApplicationThread,其中ApplicationThread繼承了IApplicationThread.Stub。app指的是傳入的要啓動的Activity所在的應用程序進程,因此這段代碼指的就是要在目標應用程序進程啓動Activity。當前代碼邏輯運行在AMS所在的進程(SystemServer系統服務進程)中,通過ApplicationThread來與應用程序進程進程Binder通信(跨進程通信),也就是說ApplicationThread是AMS和應用程序進程的通信橋樑

在這裏插入圖片描述

3.ActivityThread啓動Activity的過程

通過前面的分析,我們知道代碼邏輯目前運行到應用程序進程中,ActivityThread啓動Activity過程時序圖如下:

在這裏插入圖片描述

接着查看ApplicationThread的scheduleLaunchActivity方法,ApplicationThread是ActivityThread的內部類,ActivityThread負責管理當前應用程序進程的主線程,scheduleLaunchActivity方法代碼如下:

@Override
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);
	// 此處的r就是保存要啓動activity的信息,作爲參數通過sendMessage發送出去
	ActivityClientRecord r = new ActivityClientRecord();

    r.token = token;
    r.ident = ident;
    r.intent = intent;
    r.referrer = referrer;
    ...
    updatePendingConfiguration(curConfig);
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

​ scheduleLaunchActivity方法將啓動Activity的參數封裝成ActivityClientRecord。sendMessage方法向H類發送類型爲LAUNCH_ACTIVITY的消息,並將ActivityClientRecord傳遞出去,sendMessage方法有多個重載,最終調用的sendMessage方法如下:

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

​ 這裏的mH指的是H,它是ActivityThread的內部類並繼承Handler,是應用程序進程中主線程的消息管理類。因爲ApplicationThread是一個Binder,它的調用邏輯運行在Binder線程池(子線程)中,所以這裏需要用H將代碼的邏輯切換到主線程中。H類中處理消息的handleMessage方法如下:

public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
        case LAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            // 註釋1
            // 取出之前保存的要啓動的Activity的信息
            // 這些信息封裝在ActivityClientRecord這個類中
            final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
			// 註釋2
            // pachageinfo 指的是LoadedApk
            r.packageInfo = getPackageInfoNoCheck(
                r.activityInfo.applicationInfo, r.compatInfo);
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
        case RELAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
            ActivityClientRecord r = (ActivityClientRecord)msg.obj;
            handleRelaunchActivity(r);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
        ...
    }
    ...
}

查看H類中handleMessage方法中對LAUNCH_ACTIVITY的處理,在註釋1處將傳過來的msg的成員變量obj轉換爲ActivityClientRecord。在註釋2處通過getPackageInfoNoCheck方法獲得LoadedApk類型的對象並賦值給ActivityClientRecord的成員變量packageInfo。應用程序要啓動Activity時需要將該Activity所屬的APK加載進來,而LoadedApk就是用來描述已加載的APK文件的。接着調用handleLaunchActivity方法:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason)
 {
	...   

    // Initialize before creating the activity
    WindowManagerGlobal.initialize();
	// 註釋1
    // 啓動Activity
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        // 註釋2
        // 將Activity的狀態置爲Resume
        handleResumeActivity(r.token, false, r.isForward,
              !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

        if (!r.activity.mFinished && r.startsNotResumed) {

            performPauseActivityIfNeeded(r, reason);

            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }
    } else {
        // If there was an error, for any reason, tell the activity manager to stop us.
        try {
            // 註釋3
            // 停止Activity啓動
            ActivityManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

​ 註釋1處的performLaunchActivity方法用來啓動Activity,註釋2處的代碼用來將Activity的狀態設置爲Resume,如果該Activity爲null,就會執行註釋3處的邏輯,通知AMS停止啓動Activity,接下來進入performLaunchActivity:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) 
	// 註釋1 
    // 獲取ActivityInfo類
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        // 註釋2 
        // 獲取APK文件的描述類
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                                       Context.CONTEXT_INCLUDE_CODE);
    }
	// 註釋3
	// 獲取要啓動Activity的ComponentName類,它保存了該Activity的包名和類名
    ComponentName component = r.intent.getComponent();
    ...
	// 註釋4
    // 創建要啓動Activity的上下文
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        // 註釋5
        // 通過類加載器來創建要啓動的Activity的實例
        activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);
        ...
        }
    } catch (Exception e) {
        ...
    }

    try {
        // 註釋6
        // 創建Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        ...
        if (activity != null) {
            ...
            // 註釋7
            // 初始化Activity
            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, window, r.configCallback);

            ...
            if (r.isPersistable()) {
                // 註釋8
          		// 顧名思義下一步就是去調用Activity的onCreate方法
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            ...
        r.paused = true;
        mActivities.put(r.token, r);

    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        ...
    }
    return activity;
    }

​ 在註釋1處獲取ActivityInfo,用於存儲代碼以及AndroidManifest設置的Activity和Receiver節點信息,比如Activity的theme和launchMode。在註釋2處獲取APK文件的描述類LoadedApk。在註釋3處獲取要啓動的Activity的ComponentName類,在該類中保存了Activity的包名和類名。註釋4處用來創建要啓動Activity的上下文環境。註釋5處根據ComponentName中存儲的Activity類名,用類加載器來創建該Activity的實例。註釋6處用來創建Application,makeApplication方法內部會調用Application的onCreate方法。註釋7處調用Activity的attach方法初始化Activity,在attach方法中會創建Window對象(PhoneWindow)並與Activity自身進行關聯。在註釋8處調用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, PersistableBundle persistentState) {
    restoreHasCurrentPermissionRequest(icicle);
    // 註釋1
    // 正式進入Activity的生命週期方法
    onCreate(icicle, persistentState);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

​ 如註釋1處代碼所示,正式進入Activity的生命週期方法,根Activity的啓動流程大致分析完了,下面對大致流程進行小結一下。

4.總結

根Activity的啓動過程涉及4個進程,分別是Launcher進程、AMS所在進程(SystemServer進程)、Zygote進程、應用程序進程,首先Launcher進程向AMS請求創建根Activity,AMS會判斷根Activity所需要的應用程序進程是否存在並啓動,如果不存儲就會請求Zygote進程創建應用程序進程。應用程序進程啓動後,AMS會請求應用程序進程啓動根Activity。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章