android6.0源碼分析之Activity啓動過程

Activity最爲android開發者最熟悉的組件,由ActivityManagerService服務進行調度管理,而ActivityManagerService的啓動過程在activitymanagerservice服務源碼分析一文中進行了詳細分析,本文基於其對Activity的啓動過程進行分析,同時也將分析AMS對Activity的調度管理。


1、 Activity的啓動模式

啓動模式實際上就是爲了控制Activity與Task之間的關係,目前共有一下四種模式:standard、singleTop、singleTask以及singleInstance,默認的模式爲standard模式。
注意:建議一般的開發者不要輕易使用後兩種模式,因爲不同的模式,其出棧的順序不同,可能會導致用戶按下返回鍵時,會有不一樣的用戶體驗,對於啓動模式的分析,推薦仔細閱讀深入講解Android中Activity launchMode,這篇文章使用圖文並用的方式,很好的分析了Activity各種模式的區別,本文不再分析啓動模式。


2、Activity的啓動時機

Activity作爲android非常重要的組件,那麼我們會在哪些時機啓動它呢?
通常有如下幾種情形:
1. android AM命令
android系統爲開發者提供了adb工具,而在adb的基礎上執行adb shell就可以從PC上對手機側執行shell命令。如啓動瀏覽器:am start -n com.android.browser/com.android.browser.BrowserActivity。
2. 啓動AMS服務時
在啓動AMS服務時,在最後調用AMS的systemReady的最後階段會啓動Home界面,此時就會啓動一個Activity。
3. 調用startActivity()和startActivityForResult()方法時
這是我們最常用也最熟悉的啓動Activity的方式。


3、AM命令行啓動Activity的過程分析

在adb中可以使用AM命令,同時在應用程序中,也可以通過AM命令來啓動指定的Activity,AM是一個腳本命令,它還可以啓動Service,發送廣播等。

3.1 Am 框架層調用流程分析

adb執行Am命令後,最終會執行Am.java的main方法,其代碼如下:

//Am.java
public static void main(String[] args){
    (new Am()).run(args);
}

它調用的是抽象父類BaseCommand類的run方法:

//BaseCommand.java
public void run(String[] args){
    if(args.length<1){
        //顯示命令使用說明
        onShowUsage(System.out);
        return;
    }
    mArgs = args;
    mNextArg = 0;
    mCurArgData = null;
    try{
        onRun();
    }catch(...){...}
}

跟其他命令腳本類似,如果參數爲空,顯示使用說明,否則調用onRun()方法,它是一個抽象方法,在Am.java中有實現:

//Am.java
@Override
public void onRun() throws Exception{
    //獲取AMS
    mAm = ActivityManagerNative.getDefault();
    ...
    String op = nextArgRequired();
    if(op.equals("start")){
        //啓動Activity
        runStart();
    }else if(op.equals("startService")){
        //啓動服務
        runStartService();  
    }else if(op.equals("force-stop")){
        //強制停止
        runForceStop();
    }else if(op.equals("kill")){
        //殺死進程
        runKill();  
    }else if{
        ...
    }else{
        ...
    }
}

命令參數不同,其執行的操作不同,就本節來說,其參數爲start,所以將會執行runStart()方法來啓動Activity:

//Am.java
private void runStart() throws Exception{
    Intent intent = makeIntent(UserHandle.USER_CURRENT);
    ...
    do{
        //獲取包信息
        ...
        //設置intent的標誌位FLAG_ACTIVITY_NEW_TASK,即將啓動一個新任務
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        ParcelFileDescriptor fd = null;
        ProfilerInfo profilerInfo = null;
        if(mProfileFile != null){//處理-P選項,統計性能
            try{
                fd = openForSystemServer(new File(mProfileFile),ParcelFileDescriptior.MODE_CREATE|
                    ParcelFileDescriptor.MODE_TRUNCATE|ParcelFileDescriptor.MODE_READ_WRITE);
            }catch(...){...}
            profilerInfo = new ProfilerInfo(mProfileFile,fd,mSamplingInterval,mAutoStop);
        }
        ...
        int res;
        ...
        if(mWaitOption){//控制是否等待啓動結果,如果有-W選項,則該值爲true
            result = mAm.startActivityAndWait(null,null,intent,mimeType,null,null,0,mStartFlags,
                profilerInfo,null,mUserId);
            res = result.result;
        }else{
            res = mAm.startActivityAsUser(null,null,intent,mimeType,null,null,0,mStartFlags,
                profilerInfo,null,mUserId);
        }
        //處理一些返回結果
        ...
    }while(mRepeat > 1);
}

startActivityAsUser()最後也是調用AMS的startActivityAndWait()方法,所以Am命令框架層的調用結束,其調用時序如下:
Am框架層調用流程


3.2 AMS啓動Activity流程分析

Am命令將啓動Activity的工作交給了AMS來進行,首先看startActivityAndWait()方法,它直接調用StackSupervisor類的startActivityMayWait()方法,其代碼如下:

//ActivityStackSupervisor.java
final int startActivityMayWait(...){
    ...
    //爲了不改變用戶的intent
    intent = new Intent(intent);
    //收集目標intent的信息,在resolveActivity方法中與PKMS交互獲得
    ActivityInfo aInfo = resolveActivity(intent,resolvedType,startFlags,profilerInfo,userId);
    ActivityContainer container = (ActivityContainer)iContainer;
    synchronized(mService){
        ...
        final ActivityStack stack;
        //取得需要啓動的ActivityStack棧
        if(container == null || container.mStack.isOnHomeDisplay()){
            stack = mFocusedStack;
        }else{
            stack = container.mStack;
        }
        ...
        if(aInfo!=null&&(aInfo.applicationInfo.privateFlags&
            ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)!=0){
            //Androidmanifest.xml中的Application標籤可以聲明一個cantSaveState屬性,若設置,其將不享受系統提
            //供的狀態保存/恢復功能。主要是爲了保證用戶體驗的連續性
            ...
        }
        //啓動Activity
        int res = startActivityLocked(caller,intent,resolvedType,aInfo,voiceSession,
            voiceInteractor,resultTo,resultWho,requestCode,callingPid,callingUid,callingPackage,
            realCallingPid,realCallingUid,startFlags,options,ignoreTargetSecurity,
            componentSpecified,null,container,inTask);
        ...
        //如果配置Configration發生變化,則調用AMS的updateConfigurationLocked進行處理
        if(stack.mConfigWillChange){
            mService.enforceCallingPermission(...);
            mConfigWillChange = false;
            mService.updateConfigurationLocked(config,null,false);
        }
        if(outResult != null){
            outResult.result = res;
            if(res == IActivityManager.START_SUCCESS){
                //將結果放入mWaitingActivityLaunced中保存
                mWaitingActivityLaunched.add(outResult);
                do{
                    try{
                        //等待啓動結果
                        mService.wait();
                    }
                }while(!outResult.timeout&&outResult.who == null);
            }else if{
                ...
            }
            ...
        }
        return res;
    }
}

首先通過PKMS查找匹配的ActivityInfo,然後獲取調用者的pid,uid等信息,由於本文的caller爲空,得到的是Am所在進程的pid和uid。接着調用startActivityLocked()方法啓動Activity,最後再調用mService.wait()方法來等待啓動結果,並對返回值進行一些處理,此處的等待主要是Am參數中有一個-W選項,若無此選項,則不會有這個等待,最後再將啓動結果res返回。
繼續分析startActivityLocked()方法:

//ActivityStackSupervisor.java
final int startActivityLocked(...){
    int err = ActivityManager.START_SUCCESS;
    ProcessRecord callerApp = null;
    if (caller != null) {//如果caller不爲空,從AMS中找到它所屬的ProcessRecord即進程,本文此處爲null
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) {
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        } else {
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }
    ...
    //sourceRecord用於描述啓動目標Activity的那個Activity
    ActivityRecord sourceRecord = null;
    //resultRecord用於描述接收啓動結果的Activity,即onActivityResult將被調用以通知啓動結果
    ActivityRecord resultRecord = null;
    ...
    //獲取Intent設置的啓動標誌
    final int launchFlags = intent.getFlags();
    //此部分與LaunchMode類似,它用於控制Activity啓動結果的通知
    if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
        ...
    }
    ...
    //檢查權限
    final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, callingUid);
    ...
    //可爲AMS設置IActivityController類型的監聽者,AMS有任何動靜都將回調該監聽者
    if (mService.mController != null) {
        try {
            Intent watchIntent = intent.cloneFilter();
            //交給回調對象處理,由它判斷能否繼續後面的行程
            abort |= !mService.mController.activityStarting(watchIntent,
                        aInfo.applicationInfo.packageName);
        } catch (RemoteException e) {
            mService.mController = null;
        }
    }
    if (abort) {//通知resultRecord
        if (resultRecord != null) {
            resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                Activity.RESULT_CANCELED, null);
    }   
        ActivityOptions.abort(options);
        return ActivityManager.START_SUCCESS;
    }
    //創建一個ActivityRecord對象
    ActivityRecord r = new ActivityRecord(mService,this,callerApp,callingUid,...);
    ...
    final ActivityStack stack = mFocusedStack;
    if (voiceSession == null && (stack.mResumedActivity == null
        || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
        //判斷是否有權限切換Application
        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,realCallingPid, 
            realCallingUid, "Activity start")) {
            PendingActivityLaunch pal =new PendingActivityLaunch(r, sourceRecord,startFlags,
                stack);
            //將Pending的請求保存到AMS的mPendingActivityLaunches變量中
            mPendingActivityLaunches.add(pal);
            ActivityOptions.abort(options);
            return ActivityManager.START_SWITCHES_CANCELED;
        }
    }
    if (mService.mDidAppSwitch) {
        mService.mAppSwitchesAllowedTime = 0;
    } else {
        mService.mDidAppSwitch = true;
    }
    //啓動處於Pending狀態的Activity
    doPendingActivityLaunchesLocked(false);
    //調用此函數繼續啓動Activity
    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,startFlags, 
        true, options, inTask);
    //做一些結果處理
    ...
    return err;
}

此段代碼的主要工作就是處理sourceRecord和resultRecord,然後再處理app switch屬性,如果當前禁止app switch,則將本次啓動保存起來,等允許app switch時再處理,最後再調用startActivityUncheckedLocked()方法處理本次Activity啓動請求:

//ActivityStackSupervisor.java
final int startActivityUncheckedLocked(...) {
    final Intent intent = r.intent;
    final int callingUid = r.launchedFromUid;
    ...
    //獲取啓動標誌
    int launchFlags = intent.getFlags();
    if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&(launchSingleInstance 
        || launchSingleTask)) {
        //如果Intent和AndroidManifest.xml的啓動模式有衝突,以AndroidManifest.xml爲準
        launchFlags &=~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
    } else {
         ...
    }
    ...
    if (sourceRecord != null) {//如果請求的發起者爲空,則需要創建一個新的Task
        if (sourceRecord.finishing) {
            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                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(inTask==null){
        if(sourceRecord==null){
            //如果不是從另外的Activity啓動的,則需創建新的Task
            if((launchFlags&Intent.FLAG_ACTIVITY_MEW_TASK)==0&&inTask==null){
                launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;
            }
        }else if(sourceRecord.launchMode==ActivityInfo.LAUNCH_SINGLE_INSTANCE){
            //如果此Activity在系統中已經有實例在運行,則需要爲此Activity額外創建一個Task
            launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;
        }else if(launchSingleInstance||launchSingleTask){
            //如果是SingleInstance或者SingleTask的啓動模式,同樣需要創建新的Task
            launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;
        }
    }
    ...
    targetStack.startActivityLocked(r,newTask,doResume,keepCurTransition,options);
    ...
    return ActivityManager.START_SUCCESS;
}

首先根據Activity的啓動模式以及傳入的參數來確定是否需要創建新的Task以及launchFlags,然後調用startActivityLocked()方法繼續啓動(這裏的方法參數與前面同名方法的不一樣,屬於重載函數),繼續分析啓動過程:

//ActivityStackSupervisor.java
final void startActivityLocked(ActivityRecord r, boolean newTask,
        boolean doResume, boolean keepCurTransition, Bundle options){
    ...
    TaskRecord task = null;
    if (!newTask) {//如果不是已經存在的任務,則找到它在哪裏
        boolean startIt = true;
        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            task = mTaskHistory.get(taskNdx);
            if (task.getTopActivity() == null) {
                //此task下的Activity全部執行結束
                continue;
            }
            if (task == r.task) {
                if (!startIt) {//如果它對用戶是不可見的,只需將其加入未啓動的
                    task.addActivityToTop(r);
                    r.putInHistory();
                    ...
                    ActivityOptions.abort(options);
                    return;
                }
                break;
            }else if(task.numFullScreen > 0){
                startIt = false;
            }
        }
    }
    ...
    //將Activity信息加入到history stack中並處理
    task = r.task;
    task.addActivityToTop(r);
    task.setFrontOfTask();
    r.putInHistory();
    ...
    if(doResume){
        mStackSupervisor.resumeTopActivitiesLocked(this,r,options);
    }
}

此方法將根據傳入的參數來找到此Activity所在的任務,以及進行相應判斷將其加入到相應的history stack的最頂端(棧頂),最後再調用ActivityStack的resumeTopActivitiesLocked方法來啓動棧頂的Activity,繼續分析resumeTopActivitiesLocked方法:

//ActivityStack.java
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions){
    if (targetStack == null) {//如果目的任務爲NULL,則啓動當前聚焦的任務
        targetStack = mFocusedStack;
    }
    //啓動targetStack
    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) {
                //上面已經啓動了
                continue;
            }
            if (isFrontStack(stack)) {
                stack.resumeTopActivityLocked(null);
            }
        }
    }
    return result;
}

此方法很簡單就是根據當前任務,調用相應的resumeTopActivityLocked()方法來啓動,而resumeTopActivityLocked也只是簡單的調用了resumeTopActivityInnerLocked方法,所以分析resumeTopActivityInnerLocked方法:

//ActivityStack.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options){
    //找到第一個還沒有結束的Activity
    final ActivityRecord next = topRunningActivityLocked(null);
    ...
    //確保擁有此Activity的任務已經啓動
    if (mService.mStartedUsers.get(next.userId) == null) {
        return false;
    }
    ...
    //設置啓動的Uid
    mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
    ...
    ActivityStack lastStack = mStackSupervisor.getLastStack();
    if (next.app != null && next.app.thread != null) {//進程,線程都存在
        //將此Activity置爲Visible
        mWindowManager.setAppVisibility(next.appToken, true);
        // schedule launch ticks to collect information about slow apps.
        next.startLaunchTickingLocked();

        ActivityRecord lastResumedActivity =
                    lastStack == null ? null :lastStack.mResumedActivity;
        ActivityState lastState = next.state;

        next.state = ActivityState.RESUMED;
        mResumedActivity = next;
        next.task.touchActiveTime();
        mRecentTasks.addLocked(next.task);
        mService.updateLruProcessLocked(next.app, true, null);
        updateLRUListLocked(next);
        mService.updateOomAdjLocked();
        ...
        try {
            // Deliver all pending results.
            ArrayList<ResultInfo> a = next.results;
            if (a != null) {
                final int N = a.size();
                if (!next.finishing && N > 0) {
                    next.app.thread.scheduleSendResult(next.appToken, a);
                }
            }
            if (next.newIntents != null) {
                next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
            }
            ...
            next.sleeping = false;
            mService.showAskCompatModeDialogLocked(next);
            next.app.pendingUiClean = true;
            next.app.forceProcessStateUpTo(mService.mTopProcessState);
            next.clearOptionsLocked();
            //因爲進程,線程都存在,所以只需恢復此Activity
            next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
            mService.isNextTransitionForward(), resumeAnimOptions);
        } catch (Exception e) {
            // 如果發生異常,需要重啓此Activity,注意此方法最後一個參數爲false
            mStackSupervisor.startSpecificActivityLocked(next, true, false);
            return true;
        }
    } else {
        //因爲進程或者線程爲空,所以需要重新啓動activity,此處最後一個參數爲true
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    return true;
}

如代碼可知:如果當前需要啓動的Activity所在的進程和線程都已經創建,則調用ActivityThread的scheduleResumeActivity方法來恢復此Activity,此時如果發生異常,則調用startSpecificActivityLocked來重新啓動此Activity,當然,我們注意到,當Activity所在的進程或者線程爲啓動時,它也是調用startSpecificActivityLocked方法來重新啓動此Activity,但區別在此方法的最後一個參數,即進程和線程已經啓動了的爲flase,否則爲true,下面分析startSpecificActivityLocked()方法:

//ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {
    //先獲取app,據此app來判斷Activity所在的Application是否已經啓動
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                            r.info.applicationInfo.uid, true);
    r.task.stack.setLaunchTime(r);
    if (app != null && app.thread != null) {//進程和線程不爲空,即已經啓動好
        try {
            ...
            //真正啓動Activity的函數,注意checkConfig參數
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {...}
    }
    //進程或者線程未啓動
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
}

由代碼可知,它同樣會先判斷線程和進程是否已啓動,如果已啓動,調用realStartActivityLocked來啓動Activity,否則調用AMS的startProcessLocked來啓動進程,由於Am命令和AMS的Hone界面啓動都是進程未啓動的情況,所以此處先分析分兩個階段分析,此階段的時序圖如下:
這裏寫圖片描述


3.2.1 AMS啓動Activity所在進程的流程分析

由於android下的Java進程都是由Zygote進程fork出來的,所以分析此流程之前,需要對Zygote的原理有一些瞭解,對Zygote進程的分析請參考android源碼分析之Zygote進程分析,先從AMS的startProcessLocked方法進行分析:

//ActivityManagerService.java
private final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, 
            String abiOverride, String entryPoint, String[] entryPointArgs){
    long startTime = SystemClock.elapsedRealtime();
    if (app.pid > 0 && app.pid != MY_PID) {//如果不是當前進程,則移除
        checkTime(startTime, "startProcess: removing from pids map");
        synchronized (mPidsSelfLocked) {
            mPidsSelfLocked.remove(app.pid);
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        }
        checkTime(startTime, "startProcess: done removing from pids map");
        app.setPid(0);
    }
    ...
    //啓動進程
    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);
    ...
    //通知BatteryStatsService服務此進程啓動
    mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
    ...//對進程啓動結果進行處理
}

由代碼可知,它調用了Process的start方法來啓動進程,繼續分析start方法:

//Process.java
public static final ProcessStartResult start(...){
    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.java
private static ProcessStartResult startViaZygote(...){
    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);
        //參數處理
        ...
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}

同樣,它首先進行一些參數處理,如runtime的參數等等,繼續分析zygoteSendArgsAndGetResult方法:

//Process.java
private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, 
        ArrayList<String> args) throws ZygoteStartFailedEx{
     try {
         //通過socket通信,此處將進程啓動的啓動寫進socket的輸出流
         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);
     }
}

此方法,將會與ZygoteInit中runSelectLoop()方法啓動的socket進程通信,而Zygote進程將會爲此Activity創建新的進程,而子進程創建好後,會調用ActivityThread的主線程的main方法,所以繼續分析ActivityThread的main方法:

//ActivityThread.java
public static void main(String[] args){
    ...
    AndroidKeyStoreProvider.install();
    ...
    //啓動Looper
    Looper.prepareMainLooper();
    //創建ActivityThread,即主線程
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    //獲取主Handler
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    ...
    Looper.loop();
}

此段代碼將會創建一個主線程對象ActivityThread,並將啓動Looper以及獲取主線程的Handler來進行消息處理,並調用attach方法來進行線程處理,繼續分析attach方法:

//ActivityThread.java
//此處的system參數爲false,即不是系統進程,而在分析AMS的時候,其啓動Home界面時,此處爲true
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的attachApplication方法來對線程進行包裝,繼續查看attachApplication方法:

//ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

只是調用了attachApplicationLocked方法:

//ActivityManagerService.java
private final boolean attachApplicationLocked(IApplicationThread thread,int pid){
    //首先獲取相應的app
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid);
        }
    } else {
        app = null;
    }
    ...
    app.makeActive(thread, mProcessStats);
    app.curAdj = app.setAdj = -100;
    app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
    app.forcingToForeground = null;
    updateProcessForegroundLocked(app, false, false);
    ...
    mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
    ...
    thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
    updateLruProcessLocked(app, false, null);
    app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
    ...

    // 查看該進程是否有棧頂可視的Activity等待運行
    if (normalMode) {
        try {
            //如果有,會調用realStartActivityLocked方法啓動此Activity
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
    return true;
}

此處回調了ActivityThread的bindApplication方法,通過bindApplication方法來對應用進行相應的初始化,然後調用了ActivityStackSupervisor的attachApplicationLocked方法,它最後會調用realStartActivityLocked方法來真正啓動Activity,本節不對Activity的調度做分析,所以先分析bindApplication方法。

//ActivityThread.java
public final void bindApplication(...){
    if (services != null) {
        // Setup the service cache in the ServiceManager
        ServiceManager.initServiceCache(services);
    }
    ...
    IPackageManager pm = getPackageManager();
    android.content.pm.PackageInfo pi = null;
    ...
    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    ...
    data.persistent = persistent;
    data.config = config;
    data.compatInfo = compatInfo;
    data.initProfilerInfo = profilerInfo;
    //發送BIND_APPLICATION信號給ApplicationThread的H的handler處理
    sendMessage(H.BIND_APPLICATION, data);
    ...

    if (andResume) {
        app.hasShownUi = true;
        app.pendingUiClean = true;
    }
    app.forceProcessStateUpTo(mService.mTopProcessState);
    //通過ActivityThread調用scheduleLaunchActivity來啓動Activity
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,System.identityHashCode(r), 
        r.info, new Configuration(mService.mConfiguration),
        new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
        task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,newIntents, 
    ...
}

首先通過sendMessage發送BIND_APPLICATION信號給ApplicationThread,ApplicationThread的handler會對此進行處理。至此,有關進程和線程的流程分析結束,其時序圖如下:
這裏寫圖片描述


3.2.2 AMS對Activity的調度分析

上一節分析了進程的創建和主線程的初始化過程,本節將分析AMS對Activity生命週期的管理調度,此處涉及到的主要有如下幾個類:ActivityStackSupervisor,ActivityStack,ActivityThread,ApplicationThread,ApplicationThread.H,Instrumentation等。

系統通過AMS來管理應用進程的生命週期,當然包括應用的Activity、Service等的生命週期。AMS是一個獨立的進程,因此它要管理應用進程,必然要進行跨進程交互。其交互如下圖:
這裏寫圖片描述
其中:
ActivityManagerProxy——AMS的代理,供應用進程調用。通過ActivityManagerNative.getDefault()獲取。
ApplicationThreadProxy——應用進程的代理,供AMS進程調用。應用啓動時,會將應用進程的代理傳遞到AMS跨進程通信,一般都會用到遠程代理。ActivityManagerService繼承於Binder即它實現了IBinder接口,所以它可以用於進程間通信。在app進程啓動時,會建立一個Binder線程池,專門用來處理Binder IPC事物。
在3.2.1節中已經分析了:AMS在啓動好了進程之後,會調用realStartActivityLocked方法來啓動Activity,所以先看realStartActivityLocked方法:

//ActivityStackSupervisor.java
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),new Configuration(stack.mOverrideConfig), 
    r.compat, r.launchedFromPackage,task.voiceInteractor, app.repProcState, r.icicle, 
    r.persistentState, results,newIntents, !andResume, mService.isNextTransitionForward(), 
    profilerInfo);
    ...
}

由代碼可知:它是通過調用ActivityThread.ApplicationThread類的scheduleLaunchActivity方法來啓動Activity的:

//ActivityThread.java/ApplicationThread內部類
@Override
public final void scheduleLaunchActivity(...){
    updateProcessState(procState, false);
    ActivityClientRecord r = new ActivityClientRecord();
    r.token = token;
    r.ident = ident;
    ...
    r.startsNotResumed = notResumed;
    r.isForward = isForward;
    r.profilerInfo = profilerInfo;
    r.overrideConfig = overrideConfig;
    updatePendingConfiguration(curConfig);

    sendMessage(H.LAUNCH_ACTIVITY, r);
}

此方法將發送一個LAUNCH_ACTIVITY的Message給ApplicationThread.H的handler進行處理,而此handler將會調用ApplicationThread的handleLaunchActivity進行啓動處理:

//ActivityThread.java/ApplicationThread內部類
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent){
    ...
    //確保運行的是最近的配置
    handleConfigurationChanged(null, null);
    ...
    //在create Activity之前intialize
    WindowManagerGlobal.initialize();
    //啓動Activity,即OnCreate()
    Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        Bundle oldState = r.state;
        //調用OnResume()
        handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished 
            && !r.startsNotResumed);
        ...
    }
    ...
}

如代碼:首先調用performLaunchActivity來啓動Activity,即調用OnCreate()生命週期,然後會調用handleResumeActivity方法來調用OnResume()生命週期。首先看performLaunchActivity():

//ActivityThread.java/ApplicationThread內部類
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        //如果packageInfo爲空,從ActivityInfo中獲取包信息
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
            Context.CONTEXT_INCLUDE_CODE);
    }
    //從ActivityClientRecord中獲取組件名字
    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;
    //創建Activity
    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 (r.isPersistable()) {
        //調用OnCreate()方法
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    ...
    if (!r.activity.mFinished) {
        activity.performStart();
        r.stopped = false;
    }
    ...
    return activity;
}

此方法將會通過類加載器加載組件並新建Activity,然後通過調用Instrumentation的callActivityOnCreate方法來啓動Activity,其方法定義如下:

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

此方法裏調用了performCreate方法:

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

顯然,它最後會調用定義的Activity的OnCreate()方法,即執行了OnCreate生命週期,同理其他生命週期的執行過程與此類似。OnCreate生命週期的時序圖如下:
這裏寫圖片描述


4、startActivity方法啓動Activity的過程分析

本節將對我們熟悉的調用startActivity的啓動方式進行分析,同樣基於的源碼版本是android 6.0,這種情況下,應用進程已經存在,不需要進行應用進程的創建啓動(區別於AMS啓動Home桌面等啓動新應用的方式),首先看startActivity()代碼:

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

由代碼可知,startActivity()最終只是對startActivityForResult()方法進行簡單調用,所以只需對startActivityForResult()繼續分析:

public void startActivityForResult(Intent intent,int requestCode,@Nullable Bundle options){
    if(mParent == null){
        //執行Activity啓動,並返回啓動結果
        Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this,
            mMainThread.getApplicationThread(),mToken,this,intent,requestCode,options);
        if(ar != null){
            //向主線程發送啓動結果
            mMainThread.sendActivityResult(mToken,mEmbeddedID,requestCode,ar.getResultCode(),
                ar.getResultData());
        }
        if(requestCode > 0){
            //啓動成功
            mStartedActivity = true;
        }
        cancelInputsAndStartExitTransition(options);
    }else{
        //如果mParent不爲空,此時最後還是會調用Instrumentation的execStartActivity()方法
        if(options != null){
            mParent.startActivityFromChild(this,intent,requestCode,options);
        }else{
            mParent.startActivityFromChild(this,intent,requestCode);
        }
    }
}

最後還是會調用Instrumentation的execStartActivity()方法來啓動Activity,並將啓動的結果返回給該應用的主線程,繼續分析execStartActivity()方法:

public ActivityResult execStartActivity(Context who,IBinder contextThread,IBinder token,String 
                            target,Intent intent,int requestCode,Bundle options){
    //獲取通信存根類,它派發消息給ActivityThread主線程,而主線程的mH的handler會進行相應處理
    IApplicationThread whoThread = (IApplicationThread)contextThread;
    ...
    try{
        intent.migrateExtraStreanToClipData();
        intent.prepareToLeaveProcess();
        //調用AMS的startActivity()方法,即進入AMS的調度管理
        int result = ActivityManagerNative.getDefault().startActivity(whoThread,
            who.getBasePackageName(),intent,intent.resolveTypeIfNeeded(
                who.getContentResolver()),token,target,requestCode,0,null,options); 
        //檢查啓動結果
        checkStartActivityResult(result,intent);
    }catch(RemoteException e){
        throw new RuntimeException("Failure from system",e);
    }
    return null;
}

首先獲得IApplicationThread對象,它用於與主線程進行通信,ActivityManagerNative.getDefault()獲取的是AMS對象,所以此處將啓動任務交給了AMS進行調度管理。startActivity方法會調用startActivityAsUser()方法:

@Override
public final int startActivityAsUser(...){
    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,profierInfo,null,null,options,false,
        userId,null,null);
}

至此,它的分析同第3節中的過程一致,此處不再做分析,只是本節的啓動不需要啓動進程,所以它的執行分支不一致。

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