Android Framework之Activity啓動流程(一)

本文的分析基於Android 8.1源碼。

本文章將分三篇爲大家講解。
第二篇:Android Framework之Activity啓動流程(二)
第三篇:Android Framework之Activity啓動流程(三)

在文章的起始,插張時序圖,先看結論再看過程。
這裏寫圖片描述

Zygote

在Android系統中,是由ActivityManagerService負責爲應用程序創建新進程的。至於ActivityManagerService本身進程,則是由Zygote負責啓動。
Zygote翻譯成中文,是受精卵。至於爲啥叫這個名字,問設計Android系統的攻城獅去……
哈哈哈,開個玩笑。。。這裏寫圖片描述
在Android中,大部分的應用進程都是由zygote來創建的,是不是跟受精卵的職責有點類似, emmm……
我們來看看Zygote是如何創建ActivityManagerService進程的。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
    ……
    //這句話大概可以猜出zygote和其他進程是通過Socket來通信的
zygoteServer.registerServerSocket(socketName);
……
boolean startSystemServer = false;
    for (int i = 1; i < argv.length; i++) {
        if ("start-system-server".equals(argv[i])) {
          startSystemServer = true;
          ……
        }else if {
}
     }
……

if (startSystemServer) {
    //在forkSystemServer中fork system server進程
    Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
……
}
}

/**
 * Prepare the arguments and forks for the system server process.
 *
 * Returns an {@code Runnable} that provides an entrypoint into system_server code in the
 * child process, and {@code null} in the parent.
 */
private static Runnable forkSystemServer(String abiList, String socketName,
        ZygoteServer zygoteServer) {

// …… 我是可愛的省略號 (*╹▽╹*)
int pid;

try {
    parsedArgs = new ZygoteConnection.Arguments(args);
    ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
    ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* Request to fork the system server process */
//重點來了,通過Zygote的靜態方法來fork sytem server進程
    pid = Zygote.forkSystemServer(
            parsedArgs.uid, parsedArgs.gid,
            parsedArgs.gids,
            parsedArgs.debugFlags,
            null,
            parsedArgs.permittedCapabilities,
            parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
    throw new RuntimeException(ex);
}

/* For child process */
if (pid == 0) {
    if (hasSecondZygote(abiList)) {
        waitForSecondaryZygote(socketName);
    }
    zygoteServer.closeServerSocket();
    return handleSystemServerProcess(parsedArgs);
}
return null;
}

接下來就不進去看了,貼個Zygote.forkSystemServer方法的註釋吧

/**
     * Special method to start the system server process. In addition to the
     * common actions performed in forkAndSpecialize, the pid of the child
     * process is recorded such that the death of the child process will cause
     * zygote to exit.
*/

SystemServer進程啓動時,會順帶初始化ActivityManagerService,代碼這裏就不貼了,大家自己去搜就行。
路徑:frameworks/base/services/java/com/android/server/SystemServer.java
搜索關鍵字: ActivityManagerService


Context.startActivity()

當我們需要打開一個Activity時,是不是經常這樣幹。
這裏的Context並不是Context類,真正幹活的是ContextImpl。
我們來看看具體的代碼

@Override
public void startActivity(Intent intent, Bundle options) {
    // ……我是省略號
    mMainThread.getInstrumentation().execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity) null, intent, -1, options);
}


Instrumentation

ContextImpl又僱傭了Instrumentation來幫它幹活。
來看看具體的細節:
frameworks/base/core/java/android/app/Instrumentation.java
看看官方對Instrumentation的解釋:
https://developer.android.com/reference/android/app/Instrumentation.html
沒有梯子的小夥伴們 請點我
簡單來說,Instrumentation最主要的作用就是監控系統和應用的交互

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
   //……省略代碼
    try {
        //……省略代碼
        //關鍵,通過Binder實現進程間通信
        //api26以前,這裏應該通過ActivityManagerNative中的ActivityManagerProxy來獲得AMS的代理對象
        //ActivityManagerNative.getDefault().startActivity();
        //在api26以上,ActivityManagerProxy以及被棄用,取而代之的是以下這句
        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;
}

我們看看ActivityManager.getService()方法
frameworks/base/core/java/android/app/ActivityManager.java

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

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

getService()中調用了IActivityManagerSingleton.get()方法,而IAtivityManagerSingleton是一個單例類。
這裏可以看出IActivityManagerSingleton中採取了AIDL的方式與AMS實現了進程間通信。
因此execStartActivity()方法中的代碼邏輯實際上走到了AMS的startActivity()


ActivityManagerService

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 bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            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 bOptions, int userId) {
    //判斷調用者進程是否被隔離,若是,則會拋出SecurityException異常
    enforceNotIsolatedCaller("startActivity");
    //判斷調用者是否有權限
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage,intent,resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
        profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
}

在startActivity()中return了startActivityAsUser()方法,其中多了一個參數,

UserHandle.getCallingUserId(),這個參數會獲取調用者的UserId,AMS根據UserId確定調用者的權限。最後邏輯轉移到了ActivityStarter類。

//========================分割線 ==========================//

接下來的邏輯可能會引起各位看官的強烈不適,但不管怎樣還是要堅持看完。
以下內容涉及到ActivityStarter.java, ActivityStackSupervisor.java,ActivityStack.java以及ActivityThread.java,接下來慢慢分析這幾個類的作用。


ActivityStarter

ActivityStarter是加載Activity的控制類,收集所有的邏輯來決定如何將Intent和Flags轉爲Activity並將其與Task和Stack關聯。
ActivityStarter# startActivityMayWait()
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
ActivityStarter的調用流程:
1. startActivityMayWait()
2. startActivityLocked()
3. startActivity()
4. startActivityUnchecked()

final int startActivityMayWait(……){
//……省略代碼

//根據Intent獲取到Activity的信息
//當我們啓動一個Activity時,Intent可以是顯式的,也可以是隱式的。當Intent是顯式時,//Intent已經有了目標Activity的信息,但如果是隱式的,就需要用過ActivityStackSupervisor
//的resolveActivity來匹配了。
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

//……省略代碼
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
            aInfo, rInfo, voiceSession, voiceInteractor,resultTo, resultWho, requestCode, callingPid,
            callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
            options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,reason);
}

在ActivityStarter#startActivityLocked()裏會調用ActivityStarter#startActivity(),在這裏創建了ActivityRecord對象,存儲Activity的重要信息。


ActivityStarter# startActivity()
這個方法是不能被外界調用的,必須通過startActivityLocked來調用。

private int startActivity(/*省略參數*/){
    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;
   //先判斷caller進程是否還存在,
   //可能caller進程在發出啓動請求後就被系統kill掉了
   //獲取調用者進程並得到進程pid和uid
    if (caller != null) {
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) 
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        } else {
            ……
        }
    }
    /*省略代碼*/
    //在APP組件能運行之前,如果需要review權限的話會執行這段代碼
    //跟ActivityManagerService的mPermissionReviewRequired這個布爾值有關
    //由於本人水平有限,故沒有繼續深入分析
    if (mService.mPermissionReviewRequired && aInfo != null) {
        /*省略代碼*/
    }

    //這裏創建了一個ActivityRecord,這是一個Activity的描述類,封裝了很多Activity信息
    //官方這樣解釋:
    /**
     * An entry in the history stack, representing an activity.
     */

     ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, options, sourceRecord);
    //該函數內部會啓動因app switch禁用而被hold而等待啓動Activity的//Pending請求
    doPendingActivityLaunchesLocked(false);

    return startActivity(/*ActivityRecord*/r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity);
}

在startActivity()重載方法裏會執行
ActivityStarter# startActivityUnchecked()
該方法中會涉及到Android的啓動模式和位運算,如果對位運算不熟悉的可以 點我 來加深印象。

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
                                   boolean doResume, ActivityOptions options, TaskRecord inTask,
                                   ActivityRecord[] outActivity) {
    //該方法會校驗Intent的Flag是否是特定的Flag,
    //會涉及到各種啓動模式和Android的位運算
    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
            voiceInteractor);
    //判斷是否需要啓動新的task
    computeLaunchingTaskFlags();
    //記錄父Activity對應的TaskRecord信息
    computeSourceStack();
    mIntent.setFlags(mLaunchFlags);
    //決定是否將新Activity插入到現有的Task中
    ActivityRecord reusedActivity = getReusableIntentActivity();
    //從ActivityOptions參數中得到將Activity加入Task對應的StackId
    final int preferredLaunchStackId = (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
    /* 當新Activity插入到現有Task時的處理過程,
    *  經過Debug發現,從桌面啓動Activity,這裏reusedActivity == null
    */
    if (reusedActivity != null) {
        //……省略代碼
        //處理各種Flag的情況
    }
    //……
    //權限檢查,驗證Intent中Uri權限
    mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName, mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
    mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent, mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
    //任務棧歷史棧配置
    // 處理和WindowManagerService之間的交互
    //保證Activity對應的UI能在屏幕上顯示出來
    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition, mOptions);
    if (mDoResume) {
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && mStartActivity != topTaskActivity)) {
            //目標Task的focusable爲false或者源Task棧頂Activity總是在其他Activity          //之上
            //不恢復目標Task,只需確保它可見
            mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            //通過WindowManagerService執行app啓動動畫
            mWindowManager.executeAppTransition();
        } else {
            //如果目標棧之前不是可聚焦狀態,那麼將目標棧變爲可聚焦
            if (mTargetStack.isFocusable( && !mSupervisor.isFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityUnchecked");
            }
    //======== 註釋1 ========
    //通過ActivityStackSupervisor來恢復目標task
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions);
        }
    } else {
        //如果不需要恢復,則將Activity加入到最近活動棧中
        mTargetStack.addRecentActivityLocked(mStartActivity);
    }
    ……
    return START_SUCCESS;
}

總結來講startActivityUnchecked主要是處理棧配置和管理相關的邏輯。


ActivityStackSupervisor、ActivityStack

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
見ActivityStarter# startActivityUnchecked() 的註釋1,新開啓的Activity會調用
ActivityStackSupervisor #resumeFocusedStackTopActivityLocked().

接下來是ActivityStackSupervisor.java,相信你看到這裏已經眼花繚亂了,其實我也一樣,爲了研究Activity的啓動流程,不得不堅持 read the fucking source code.
什麼?講髒話?NO,NO,不存在的。這裏寫圖片描述

簡單說一下ActivityStack和ActivityStackSupervisor這兩個類吧。
ActivityStack:負責管理在Stack和Task中的Activity
ActivityStackSupervisor:負責管理Stack和Task的操作,可以理解爲管理ActivityStack
兩者相互調用, 最終完成啓動Activity。

看看這兩個類中的代碼是如何調用的。是不是有點想罵*(手動屏蔽)的衝動。
ActivityStackSupervisor#resumeFocusedStackTopActivityLocked() ->
ActivityStack#resumeTopActivityUncheckedLocked()->
ActivityStack#resumeTopActivityInnerLocked()->
ActivityStackSupervisor# startSpecificActivityLocked ()->
ActivityStackSupervisor # realStartActivityLocked ()

重點看看ActivityStack#resumeTopActivityInnerLocked()
在使用Android Studio進行代碼跟蹤,發現走的是以下流程。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options){
    final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
    final boolean hasRunningActivity = next != null;
    mStackSupervisor.cancelInitializingActivities();
    ……
    //重點看這裏,這裏調用了StackSupervisor# pauseBackStacks方法,
    //該方法會遍歷所有任務棧,並調用ActivityStack#startPausingLocked()
    //暫停處於棧內的所有Activity
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
    if (next.app != null && next.app.thread != null) {
    ……
    } else {
    //調用了ActivityStackSupervisor# startSpecificActivityLocked
    mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
}

ActivityStackSupervisor# startSpecificActivityLocked()

void startSpecificActivityLocked(ActivityRecord r,
                                 boolean andResume, boolean checkConfig) {
    //這裏根據processName和UID在系統中查找是否已經有相應的進程存在
    //如果之前app進程不存在,則app=null
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);
    r.getStack().setLaunchTime(r);
    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags& ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                //向PreocessRecord中增加對應的package信息
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                        mService.mProcessStats);
            }
            //======== 註釋2 ========
            //若app進程存在,通知進程啓動目標Activity
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
    }
    //======== 註釋3 ========
    //若進程不存在,則使用AMS開啓一個新進程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);
}

這裏有兩種情況
① 註釋2處:創建activity之前進程存在,則會執行realStartActivityLocked()
② 註釋3處:創建activity之前進程不存在,ActivityManagerService會調用startProcessLocked()方法創建一個新進程。

先來看第一種情況:
ActivityStackSupervisor#realStartActivityLocked()
見名知意,這裏應該就是真正啓動Activity的地方。難道到這裏就結束了嗎?並不是的,具體還請各位看官繼續往下翻。

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                                      boolean andResume, boolean checkConfig) throws RemoteException {
    //獲得已存在的Task和Stack
    final TaskRecord task = r.getTask();
    final ActivityStack stack = task.getStack();

    //推遲resume,避免在一個循環中多次resume
    beginDeferResume();
    //開始凍結屏幕
    r.startFreezingScreenLocked(app, 0);
    //開始收集啓動信息
    r.startLaunchTickingLocked();
    r.app = app;

    if (checkConfig) {
        final int displayId = r.getDisplayId();
        final Configuration config =mWindowManager.updateOrientationFromAppTokens(
                getDisplayOverrideConfiguration(displayId),r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId);
        //當顯示方向改變時,推遲resume,防止啓動多餘的Activity
        mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */,displayId);
    }
    //更新進程使用情況
    mService.updateLruProcessLocked(app, true, null);
    //更新進程OomAdj
    mService.updateOomAdjLocked();
    try {
        //如果ProcessRecord爲空,則拋異常
        if (app.thread == null) {
            throw new RemoteException();
        }
         ……
        //更新package最後一次使用的時間
        mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
        app.forceProcessStateUpTo(mService.mTopProcessState);

        //官方解釋:可能用戶是從系統進程啓動的Activity,如果那樣的話就不會走到//用來創建新配置的Binder接口,因此先在這裏創建一個配置
        final MergedConfiguration mergedConfiguration = new MergedConfiguration(
                mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
        r.setLastReportedConfiguration(mergedConfiguration);

        //通過Binder調用ApplicationThread的scheduleLaunchActivity()
        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);

        // …… 處理進程臃腫的情況
    } catch(RemoteException e){
        ……
        //會進行兩次操作,第一次重啓進程失敗後再拋出異常執行第二次操作
        //第二次失敗後就放棄
    }
}

realStartActivityLocked方法主要乾了兩件事:
① 更新AMS中各種配置
② 調用ApplicationThread# scheduleLaunchActivity()啓動Activity

ActivityStackSupervisor#realStartActivityLocked()結束
ApplicationThread# scheduleLaunchActivity()的情況以及第二種進程未啓動的情況將在第三篇文章爲各位看官分析進程的創建和啓動,敬請期待。
想直接看第三篇的朋友 請點我

下一篇:Android Framework之Activity啓動流程(二)


參考:
https://blog.csdn.net/chenkai19920410/article/details/54344295
https://blog.csdn.net/gaugamela/article/details/53183216
https://blog.csdn.net/Gaugamela/article/details/53895040

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