Activity 啟動流程分析

以在桌面點擊一個App圖標冷啟動為例揖闸,Activity的啟動大致可以總結(jié)為如下流程:

一個應(yīng)用對應(yīng)一個進程或多個進程,四大組件等所有組件的運行都依附于這些進程贮泞, 所以啟動一個應(yīng)用時沒有相應(yīng)的進程存在,則會先啟動一個進程幔烛,接著啟動其組件啃擦。

  1. 點擊桌面Launcher上點擊應(yīng)用圖標時,會通知ActivityManagerService(后面簡稱AMS)啟動應(yīng)用的入口Activity饿悬,此時AMS會檢查改應(yīng)用是否已經(jīng)啟動;
  2. 如果該應(yīng)用已經(jīng)啟動珠叔,那么該應(yīng)該對應(yīng)的進程也必然存在,此時則直接顯示上次退出前打開的Activity;
  3. 如果該應(yīng)用未啟動,則AMS會通知Zygote進程fork這個應(yīng)用的進程,然后在這個dalvik應(yīng)用進程里執(zhí)行ActivityThreadmain;
  4. 進程啟動成功后, AMS會保存這個進程的一個代理對象ActivityThread择懂,此后AMS會使用這個`代理對象和應(yīng)用進程通信慷丽;
  5. AMS通知應(yīng)用進程創(chuàng)建入口Activity的實例锄俄,同時執(zhí)行Activity生命周期方法药有。
為了更好的理清楚Activity的啟動流程羊苟,我們先看看和AMS管理Activity相關(guān)幾個類的作用及其關(guān)系,如下圖:
AMS類圖.png

1 ActivityManagerService
它是管理activity的入口類稽寒,聚合了ProcessRecord對象和ActivityStack對象 ;
Android中最核心的服務(wù),主要負責系統(tǒng)中四大組件的啟動、切換、調(diào)度及應(yīng)用程序的管理和調(diào)度等工作。
負責系統(tǒng)中四大組件的啟動、切換、調(diào)度及應(yīng)用進程的管理和調(diào)度等工作。

  1. ProcessRecord
    表示應(yīng)用進程記錄酸休,每個應(yīng)用進程都有對應(yīng)的ProcessRecord對象

  2. ActivityStack
    該類主要管理回退棧, 單個活動棧的狀態(tài)和管理宿刮。
    ActivityStack管理ActivityRecord時磕潮,將屬于同一個task的ActivityRecord放在一起
    負責單個Activity棧的狀態(tài)和管理冤今。

  3. TaskRecord
    Task記錄信息龟糕,一個Task可能有多個ActivityRecord衬以,但是一個ActivityRecord只能屬于一個TaskRecord
    ActivityManagerService組織回退棧時以ActivityRecord為基本單位, 但是ActivityManagerService調(diào)度ActivityRecord時以task為基本單位互妓,
    每個ActivityRecord對象都屬于某個TaskRecord,一個TaskRecord可能有多個ActivityRecord。

  4. ActivityRecord
    每次啟動一個Actvity會有一個對應(yīng)的ActivityRecord對象,表示Activity的一個記錄

  5. ActivityInfo
    Activity的信息,比如啟動模式军熏,taskAffinity,flag信息(這些信息在AndroidManifest.xml里聲明Activity時填寫)

順便介紹下啟動過程中其他主要相關(guān)的類

  1. ActivityManager
    此類提供有關(guān)活動或衡,服務(wù)和包含過程的信息和交互彬呻。
    該類提供與Activity狱意、Service和Process相關(guān)的信息以及交互方法, 可以被看作是ActivityManagerService的輔助類捌臊。
    IActivityManager:用于與ActivityManagerService交談的系統(tǒng)專用API糠爬。 提供了從應(yīng)用程序返回到活動管理器的調(diào)用峦嗤。

  2. ActivityStarter
    用于解釋如何啟動活動的控制器凡壤。此類收集用于確定如何將意圖和標志轉(zhuǎn)變?yōu)榛顒右约跋嚓P(guān)任務(wù)和堆棧的所有邏輯硝烂。

  3. ActivityStackSupervisor
    Activity棧管理。負責所有Activity棧的管理喘漏。內(nèi)部管理了mHomeStack喂链、mFocusedStack 和 mLastFocusedStack三個Activity棧。其中间狂,mHomeStack管理的是Launcher相關(guān)的Activity棧;
    mFocusedStack管理的是當前顯示在前臺Activity的Activity棧隔盛;
    mLastFocusedStack管理的是上一次顯示在前臺Activity的Activity棧陕凹。

  4. ActivityThread
    管理應(yīng)用程序進程中主線程的執(zhí)行浆兰,根據(jù)ActivityManager請求調(diào)度和執(zhí)行Activitys、broadcasts和其他操作族壳。ActivityThread 運行在UI線程(主線程)拢操,App的真正入口玲昧。
    管理應(yīng)用程序進程中主線程的執(zhí)行惶凝,根據(jù)Activity管理者的請求調(diào)度和執(zhí)行activities洒疚、broadcasts及其相關(guān)的操作喊括。

  5. ApplicationThread
    ActivityThread內(nèi)部類劫拢,IApplicationThread.aidl的具體實現(xiàn)牵寺,提供給ActivityManager玉凯,ActivityManager通過它告知應(yīng)用程序?qū)⒁龅氖隆?br> H:繼承Handler狸眼,ActivityThread內(nèi)部類炕倘,是應(yīng)用程序進程中主線程的消息管理類浴骂。

  6. Instrumentation
    字面意思“儀器”尽棕。官方解釋:用于實現(xiàn)應(yīng)用程序檢測代碼的基類份氧。 當開啟儀器運行時,該類將在任何應(yīng)用程序代碼之前為您實例化活翩,從而允許您監(jiān)視系統(tǒng)與應(yīng)用程序之間的所有交互。Instrumentation實現(xiàn)通過AndroidManifest.xml向系統(tǒng)描述扫尖。

Activity的啟動流程:

我畫了一張詳細的流程圖彻坛,邊看流程圖邊看源碼可能效果更佳

activity啟時序圖.png

主要分為三個部分:

  1. Launcher 請求 AMS 過程;

  2. AMS 調(diào)用 ApplicationThread饥脑;

  3. ActivityThread 啟動 Activity赋除;

1. Launcher 請求 AMS 過程最盅;

點擊一個App桌面圖標其實是啟動這個App的入口Activity激挪,會調(diào)用Activity的startActivity方法, 此時使用的啟動模式是 Intent.FLAG_ACTIVITY_NEW_TASK砸逊, 因此該Activity會在一個新的任務(wù)棧中啟動;

xref:/frameworks/base/core/java/android/app/Activity.java

@Override
 public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
             startActivityForResult(intent, -1, options);
        } else {
             // Note we want to go through this call for compatibility with
             // applications that may have overridden the method.
             startActivityForResult(intent, -1);
        }
 }

startActivity有幾個其他重載的方法淆攻,無論哪個纸镊,最終都會執(zhí)行到 startActivityForResult 方法弄贿。如果是調(diào)用 startActivity(intent)啟動Activity,那么requestCode參數(shù)則傳入-1饵沧,表示當前Activity啟動一個新的Activity后领曼,不需要獲取新的Activity返回來的數(shù)據(jù)

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

mParent是Activity父類恍风,是ActivityGroup類型, 表示當前Activity的容器滞项, API 13以后已被廢棄狭归;此時mParent==null 為 true,所以接下來會執(zhí)行 mInstrumentation.execStartActivity 方法文判;Instrumentation 是用來監(jiān)控應(yīng)用程序和系統(tǒng)的交互过椎;

mMainThreadActivityThread類型的對象;
ApplicationThread 繼承了 IApplicationThread.Stub,使用了AIDL技術(shù)實現(xiàn)進程間通信戏仓。在Android 8.0之前沒有使用AIDL疚宇, 手寫了一套類似于AIDL的代碼;
IApplicationThread 是一個AIDl接口赏殃,繼承了IInterface接口灰嫉;Stub是接口IApplicationThread的內(nèi)部類,繼承了Binder類嗓奢,實現(xiàn)了IApplicationThread接口讼撒。因此ApplicationThread就是一個Binder對象察署,它重寫了IApplicationThread接口的抽象方法葛账。
源碼如下:

public final class ActivityThread {
    
    final ApplicationThread mAppThread = new ApplicationThread();
    ...
    private class ApplicationThread extends IApplicationThread.Stub {
        ...
    }
}

mMainThread對象初始化在當前Activity的attach方法中, attach方法在啟動Activity之前被調(diào)用鼠锈,attach方法主要是注冊一些接 口蝌矛,給一些變量初始化值佛嬉,其中就創(chuàng)建了PhoneWindow的實例蛉迹,為創(chuàng)建WindowManagerImpl對象做準備稠诲。通過WindowManager可以添加舵匾,刪除诬乞,更新窗口册赛,從代碼角度來說 ,增加震嫉,刪除森瘪,更新操作的是View;
下面是Activity attach方法源碼:

 final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);

        setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
        enableAutofillCompatibilityIfNeeded();
    }

接著上面activity啟動流程票堵,調(diào)用mInstrumentation.execStartActivity
xref:/frameworks/base/core/java/android/app/Instrumentation.java

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            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;
    }
}

這里調(diào)用了AMS的startActivity方法扼睬,那么Launcher是如何和AMS進程通信的呢, 其實通過 ActivityManager.getService()方法獲取到了悴势, 具體如何獲取的看如下代碼:

xref:/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;
           }
       };

IActivityManager 是一個aidl接口窗宇,里面定義了啟動和停止四大組件的相關(guān)方法措伐;該aidl接口路徑為:

xref:/frameworks/base/core/java/android/app/IActivityManager.aidl

要實現(xiàn)進程間通信,服務(wù)端AMS就要繼承IActivityManager.stub,同時實現(xiàn)相應(yīng)方法就可以军俊;這是8.0的做法侥加;

Android 8.0之前是手動寫了一個類似于aidl接口的方式去做的,用AMS的代理對象ActivityManagerProxy來與AMS進行進程間通信粪躬,
Android 8.0 去除了ActivityManagerNative的內(nèi)部類ActivityManagerProxy官硝,代替它的則是IActivityManager,它是AMS在本地的代理短蜕。

Singleton是一個抽象類,有一個抽象方法create()傻咖。有一個get()方法朋魔,內(nèi)部通過單例模式創(chuàng)建T對象,調(diào)用create方法創(chuàng)建T對象卿操,且只會創(chuàng)建一次T對象;
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
獲取一個關(guān)聯(lián)系統(tǒng)服務(wù)的Binder對象害淤;
IActivityManager.Stub.asInterface(b) 會返回實現(xiàn)了 IActivityManager 接口的代理對象扇雕, 基于Binder機制,通過代理對象調(diào)用系統(tǒng)服務(wù) ActivityManagerService 對應(yīng)的方法窥摄;

這里調(diào)用AMS的startActivity方法后镶奉, 接下來的調(diào)用流程就會進入AMS進程,也就是system_server進程崭放;

2. AMS 調(diào)用 ApplicationThread哨苛;

xref:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
           resultWho, requestCode, startFlags, profilerInfo, bOptions,
           UserHandle.getCallingUserId());
}
 @Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    enforceNotIsolatedCaller("startActivity");
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
            userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
           resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
           profilerInfo, null, null, bOptions, false, userId, null, null,
           "startActivityAsUser");
}

mUserController.handleIncomingUser 通過獲取getCallingPid 和 userid去檢查調(diào)用者的權(quán)限;
倒數(shù)第二個參數(shù)TaskRecord 類型币砂,代表的是要啟動的activity所在的棧建峭;

xref:/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, 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是Android 7.0新加入的類,它是加載Activity的控制類决摧,會收集所有的邏輯來決定如何將Intent和Flags轉(zhuǎn)換為Activity亿蒸,并將Activity和Task以及Stack相關(guān)聯(lián);

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) {
                
        if (TextUtils.isEmpty(reason)) {//1
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord[0] = null;
        
        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;
 }
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;
  final Bundle verificationBundle = options != null ? options.popAppVerificationBundle() : null;
  ProcessRecord callerApp = null;
  if (caller != null) {//1
      //獲取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;
      }
   }
        ...
   //創(chuàng)建即將要啟動的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); //2  
   if (outActivity != null) {
       outActivity[0] = r;
   }
   ...
   doPendingActivityLaunchesLocked(false);
   return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
           options, inTask, outActivity);
 }

ProcessRecord callerApp代表的是 Launcher 的 ApplicationThread掌桩,然后獲取到callingUid边锁,callingPid等信息,接著創(chuàng)建即將要啟動的activity的bean類 ActivityRecord波岛;

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();
        result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                   startFlags, doResume, options, inTask, outActivity);
   } finally {
       // If we are not able to proceed, disassociate the activity from the task. Leaving an
       // activity in an incomplete state can lead to issues, such as performing operations
       // without a window container.
       if (!ActivityManager.isStartResultSuccessful(result)
               && mStartActivity.getTask() != null) {
           mStartActivity.getTask().removeActivity(mStartActivity);
       }
       mService.mWindowManager.continueSurfaceLayout();
   }

   postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord, mTargetStack);
   return result;
 }
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
    ...
    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        //創(chuàng)建新的TaskRecord
       result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, preferredLaunchStackId, topStack);//2
   } else if (mSourceRecord != null) {
       result = setTaskFromSourceRecord();
   } else if (mInTask != null) {
       result = setTaskFromInTask();
   } else {
       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");
           }
           mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,mOptions);
      }
   } else {
       mTargetStack.addRecentActivityLocked(mStartActivity);
   }
   ...
}

由于啟動的activity 的launcherMode 為 FLAG_ACTIVITY_NEW_TASK砚蓬, 所以此時會通過setTaskFromReuseOrCreateNewTask方法去為該activity創(chuàng)建一個任務(wù)棧,

xref:/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

boolean resumeFocusedStackTopActivityLocked() {
    return resumeFocusedStackTopActivityLocked(null, null, null);
}

boolean resumeFocusedStackTopActivityLocked(
    ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
   final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
   if (r == null || r.state != RESUMED) {
       mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
   } else if (r.state == RESUMED) {
       // Kick off any lingering app transitions form the MoveTaskToFront operation.
       mFocusedStack.executeAppTransition(targetOptions);
   }
   return false;
}

mFocusedStack類型為 ActivityStack

xref:/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

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;
       result = resumeTopActivityInnerLocked(prev, options);
   } finally {
       mStackSupervisor.inResumeTopActivity = false;
   }
   mStackSupervisor.checkReadyForSleepLocked();
   return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity);     
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
    ...    
}

此處由于當前正在顯示的activity是執(zhí)行了onResume方法的盆色,所以此處的 mResumedActivity != null 灰蛙, 因此會執(zhí)行startPausingLocked方法去pause祟剔,

 final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
             ActivityRecord resuming, boolean pauseImmediately) {
       ...          
       if (prev.app != null && prev.app.thread != null) {
           prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                   userLeaving, prev.configChangeFlags, pauseImmediately);
       ...            
}  

這里的prev.app.thread是一個遠程IApplicationThread對象,通過調(diào)用這個遠程對象的schedulePauseActivity來通知Launcher進入Paused狀態(tài)摩梧,另外就是此刻由于Launcher還沒Pause物延,所以prev.finishing屬性為false。

private class ApplicationThread extends IApplicationThread.Stub {
     public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
         int seq = getLifecycleSeq();
         if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this + " operation received seq: " + seq);
         sendMessage(
                  finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                  token,
                  (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                  configChanges,
                  seq);
       }
}
private class H extends Handler {
    public static final int LAUNCH_ACTIVITY         = 100;
    public static final int PAUSE_ACTIVITY          = 101;
    
    ...
    
    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
               ...
               case PAUSE_ACTIVITY: {
                   Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                   SomeArgs args = (SomeArgs) msg.obj;
                   handlePauseActivity((IBinder) args.arg1, false,
                           (args.argi1 & USER_LEAVING) != 0, args.argi2,
                           (args.argi1 & DONT_REPORT) != 0, args.argi3);
                   maybeSnapshot();
                   Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
              } break;
              
              ...
private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
     ActivityClientRecord r = mActivities.get(token);
     if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
     if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
         return;
     }
     if (r != null) {
         //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
         if (userLeaving) {
             performUserLeavingActivity(r);
         }

         r.activity.mConfigChangeFlags |= configChanges;
         performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

         // Make sure any pending writes are now committed.
         if (r.isPreHoneycomb()) {
             QueuedWork.waitToFinish();
         }

         // Tell the activity manager we have paused.
         if (!dontReport) {
             try {
                 ActivityManager.getService().activityPaused(token);
             } catch (RemoteException ex) {
                 throw ex.rethrowFromSystemServer();
             }
         }
        mSomeActivitiesChanged = true;
    }
}

調(diào)用performPauseActivity方法來調(diào)用Activity.onPause方法仅父。
調(diào)用ActivityManagerNative.getDefault()對象的activityPaused方法來通知ActivityManagerService處理剩下的事情叛薯。

xref:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final void activityPaused(IBinder token) {
    final long origId = Binder.clearCallingIdentity();
    synchronized(this) {
        ActivityStack stack = ActivityRecord.getStackLocked(token);
        if (stack != null) {
            stack.activityPausedLocked(token, false);
        }
    }
   Binder.restoreCallingIdentity(origId);
}

xref:/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

final void activityPausedLocked(IBinder token, boolean timeout) {
     final ActivityRecord r = isInStackLocked(token);
     if (r != null) {
         mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
         if (mPausingActivity == r) {
             mService.mWindowManager.deferSurfaceLayout();
             try {
                 completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
             } finally {
                mService.mWindowManager.continueSurfaceLayout();
            }
            return;
        } else {
            if (r.state == ActivityState.PAUSING) {
                r.state = ActivityState.PAUSED;
                if (r.finishing) {
                        finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false);
                    }
               }
            }
       }
        mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}

resumeNext參數(shù)傳入的值為true;首先會清空一些狀態(tài)笙纤,將mPausingActivity指向的Activity狀態(tài)設(shè)置為PAUSED耗溜,隨后并置為null。接著調(diào)用ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()函數(shù)去啟動當前任務(wù)棧頂端的Activity省容,即目標Activity:

private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
    ActivityRecord prev = mPausingActivity;
    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
    if (prev != null) {
        final boolean wasStopping = prev.state == STOPPING;
        prev.state = ActivityState.PAUSED;
        ...
        mPausingActivity = null;
    }
     if (resumeNext) {
   final ActivityStack topStack = mStackSupervisor.getFocusedStack();
   if (!mService.isSleepingOrShuttingDownLocked()) {
          mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
   } else {
          mStackSupervisor.checkReadyForSleepLocked();
          ActivityRecord top = topStack.topRunningActivityLocked();
          if (top == null || (prev != null && top != prev)) {
               mStackSupervisor.resumeFocusedStackTopActivityLocked();
          }
   }
}
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;
       result = resumeTopActivityInnerLocked(prev, options);
   } finally {
       mStackSupervisor.inResumeTopActivity = false;
   }
   mStackSupervisor.checkReadyForSleepLocked();
   return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
      ...
           mStackSupervisor.startSpecificActivityLocked(next, true, true);
       }
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
       return true;
}

此時,如果應(yīng)用進程已經(jīng)啟動,則會去直接啟動Activity;否則,先為它啟動一個進程
mResumedActivity/mPausingActivity都以置為null抖拴;因為,我們需要啟動的Activity它的應(yīng)用進程并未創(chuàng)建過腥椒,所以這里需要為它創(chuàng)建一個應(yīng)用進程:

xref:/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

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.getStack().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);
}

這里的mService代表的是ActivityManagerService, 首先獲取即將要啟動的activity的所在應(yīng)用程序的進程阿宅, 如果進程已經(jīng)存在就調(diào)用realStartActivityLocked方法
如果應(yīng)用進程已經(jīng)啟動了,則調(diào)用該函數(shù)繼續(xù)處理;其會觸發(fā)類的onCreate()方法,否則先啟動一個進程

xref:/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

private final void startProcessLocked(ProcessRecord app, String hostingType,
3768            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
3769        long startTime = SystemClock.elapsedRealtime();
3770        if (app.pid > 0 && app.pid != MY_PID) {
    
    
     startResult = Process.start(entryPoint,
3926                        app.processName, uid, uid, gids, debugFlags, mountExternal,
3927                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
3928                        app.info.dataDir, invokeWith, entryPointArgs);
    }

AMS為應(yīng)用創(chuàng)建進程是借助fork機制實現(xiàn)的,并指定了應(yīng)用進程的入口函數(shù)是ActivityThread::main()
Zygote進程孵化出新的應(yīng)用進程后笼蛛,會執(zhí)行ActivityThread類的main方法洒放。在該方法里會先準備好Looper和消息隊列,然后調(diào)用attach方法將應(yīng)用進程綁定到ActivityManagerService滨砍,然后進入loop循環(huán)往湿,不斷地讀取消息隊列里的消息,并分發(fā)消息惋戏。

xref:/frameworks/base/core/java/android/app/ActivityThread.java

public static void main(String[] args) {
    ...
    CloseGuard.setEnabled(false);
    Environment.initForCurrentUser();
    EventLogger.setReporter(new EventLoggingReporter());
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore.setDefaultUserDirectory(configDir);
    Process.setArgV0("<pre-initialized>");
    Looper.prepareMainLooper();
   ActivityThread thread = new ActivityThread();
   thread.attach(false);
   if (sMainThreadHandler == null) {
       sMainThreadHandler = thread.getHandler();
   }
   ...
   Looper.loop();
}

xref:/frameworks/base/core/java/android/app/ActivityThread.java

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            @Override
            public void run() {
                ensureJitEnabled();
            }
       });
   
       android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());
       RuntimeInit.setApplicationObject(mAppThread.asBinder());
       final IActivityManager mgr = ActivityManager.getService();
       try {
           mgr.attachApplication(mAppThread);
       } catch (RemoteException ex) {
           throw ex.rethrowFromSystemServer();  
       }

       // Watch for getting close to heap limit.
       BinderInternal.addGcWatcher(new Runnable() {
           @Override public void run() {
               if (!mSomeActivitiesChanged) {
                   return;
               }
               Runtime runtime = Runtime.getRuntime();
               long dalvikMax = runtime.maxMemory();
               long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
               if (dalvikUsed > ((3*dalvikMax)/4)) {
               if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                        + " total=" + (runtime.totalMemory()/1024)
                        + " used=" + (dalvikUsed/1024));
                   mSomeActivitiesChanged = false;
                   try {
                       mgr.releaseSomeActivities(mAppThread);
                   } catch (RemoteException e) {
                       throw e.rethrowFromSystemServer();
                   }
               }
          }
     });
   } else {
       // Don't set application object here -- if the system crashes,
       // we can't display an alert, we just want to die die die.
       android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId());
       try {
           mInstrumentation = new Instrumentation();
           ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
           mInitialApplication = context.mPackageInfo.makeApplication(true, null);
           mInitialApplication.onCreate();
       } catch (Exception e) {
           throw new RuntimeException("Unable to instantiate Application():" + e.toString(), e);
       }
   }

   // add dropbox logging to libcore
   DropBox.setReporter(new DropBoxReporter());

   ViewRootImpl.ConfigChangedCallback configChangedCallback= (Configuration globalConfig) -> {
       synchronized (mResourcesManager) {
           // We need to apply this change to the resources immediately, because upon returning
           // the view hierarchy will be informed about it.
           if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,null /* compat */)) {
               updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                   mResourcesManager.getConfiguration().getLocales());

               // This actually changed the resources! Tell everyone about it.
               if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
                   mPendingConfiguration = globalConfig;
                   sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
               }
           }
       }
   };
   ViewRootImpl.addConfigCallback(configChangedCallback);
 }

xref:/frameworks/base/services/core/java/com/android/server/am/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);
    }
}

xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
    try {
         ...
         thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                app.instrumentationUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(mConfiguration), app.compat,
               getCommonServicesLocked(app.isolated),
               mCoreSettingsObserver.getCoreSettingsLocked());//調(diào)用bindApplication()方法
        updateLruProcessLocked(app, false, null);
        app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
   } catch (Exception e) {
           ...
   }
        
   if (normalMode) {
   try {
       if (mStackSupervisor.attachApplicationLocked(app)) {
             didSomething = true;
       }
   } catch (Exception e) {
 }
}

thread對象其實是ActivityThread里ApplicationThread對象在ActivityManagerService的代理對象煌茴,故此執(zhí)行thread.bindApplication,最終會調(diào)用ApplicationThread的bindApplication方法

public final void bindApplication(String processName, ApplicationInfo appInfo,
             List<ProviderInfo> providers, ComponentName instrumentationName,
             ProfilerInfo profilerInfo, Bundle instrumentationArgs,
             IInstrumentationWatcher instrumentationWatcher,
             IUiAutomationConnection instrumentationUiConnection, int debugMode,
             boolean enableBinderTracking, boolean trackAllocation,
             boolean isRestrictedBackupMode, boolean persistent, Configuration config,
             CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
             String buildSerial) {
    
    if (services != null) {
        // Setup the service cache in the ServiceManager
        ServiceManager.initServiceCache(services);
    }

    setCoreSettings(coreSettings);

    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    data.instrumentationName = instrumentationName;
    data.instrumentationArgs = instrumentationArgs;
    data.instrumentationWatcher = instrumentationWatcher;
    data.instrumentationUiAutomationConnection = instrumentationUiConnection;
    data.debugMode = debugMode;
    data.enableBinderTracking = enableBinderTracking;
    data.trackAllocation = trackAllocation;
    data.restrictedBackupMode = isRestrictedBackupMode;
    data.persistent = persistent;
    data.config = config;
    data.compatInfo = compatInfo;
    data.initProfilerInfo = profilerInfo;
    data.buildSerial = buildSerial;
    sendMessage(H.BIND_APPLICATION, data);
  }
private void handleBindApplication(AppBindData data) {
     VMRuntime.registerSensitiveThread();
     if (data.trackAllocation) {
         DdmVmInternal.enableRecentAllocations(true);
     }

     // Note when this process has started.
     Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());

    // send up app name; do this *before* waiting for debugger
    Process.setArgV0(data.processName);
    android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId());

    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
 
    final InstrumentationInfo ii;
    if (data.instrumentationName != null) {
        try {
            ii = new ApplicationPackageManager(null, getPackageManager())
                     .getInstrumentationInfo(data.instrumentationName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
                    "Unable to find instrumentation info for: " + data.instrumentationName);
        }

        mInstrumentationPackageName = ii.packageName;
        mInstrumentationAppDir = ii.sourceDir;
        mInstrumentationSplitAppDirs = ii.splitSourceDirs;
        mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
        mInstrumentedAppDir = data.info.getAppDir();
        mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
        mInstrumentedLibDir = data.info.getLibDir();
    } else {
        ii = null;
    }

    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    updateLocaleListFromAppContext(appContext, mResourcesManager.getConfiguration().getLocales());

    if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {
        // This cache location probably points at credential-encrypted
        // storage which may not be accessible yet; assign it anyway instead
        // of pointing at device-encrypted storage.
        final File cacheDir = appContext.getCacheDir();
        if (cacheDir != null) {
            // Provide a usable directory for temporary files
            System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
        } else {
            Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property "+ "due to missing cache directory");
    }

    // Setup a location to store generated/compiled graphics code.
    final Context deviceContext = appContext.createDeviceProtectedStorageContext();
    final File codeCacheDir = deviceContext.getCodeCacheDir();
    if (codeCacheDir != null) {
        setupGraphicsSupport(appContext, codeCacheDir);
    } else {
        Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
    }
   
    // Continue loading instrumentation.
    if (ii != null) {
        final ApplicationInfo instrApp = new ApplicationInfo();
        ii.copyTo(instrApp);
        instrApp.initForUser(UserHandle.myUserId());
        final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                  appContext.getClassLoader(), false, true, false);
        final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

        try {
            final ClassLoader cl = instrContext.getClassLoader();
            mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Unable to instantiate instrumentation "
                  + data.instrumentationName + ": " + e.toString(), e);
        }
        final ComponentName component = new ComponentName(ii.packageName, ii.name);
        mInstrumentation.init(this, instrContext, appContext, component,
                  data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
        if (mProfiler.profileFile != null && !ii.handleProfiling && mProfiler.profileFd == null) {
            mProfiler.handlingProfiling = true;
            final File file = new File(mProfiler.profileFile);
            file.getParentFile().mkdirs();
            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
        }
    } else {
        mInstrumentation = new Instrumentation();
    }

    if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
    } else {
        // Small heap, clamp to the current growth limit and let the heap release
        // pages after the growth limit to the non growth limit capacity. b/18387825
        dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
    }

    // Allow disk access during application and provider setup. This could
    // block processing ordered broadcasts, but later processing would
   // probably end up doing the same disk access.
   final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
   try {
       // If the app is being launched for full backup or restore, bring it up in
       // a restricted environment with the base application class.
       Application app = data.info.makeApplication(data.restrictedBackupMode, null);
       mInitialApplication = app;

       // Do this after providers, since instrumentation tests generally start their
       // test thread at this point, and we don't want that racing.
       try {
           mInstrumentation.onCreate(data.instrumentationArgs);
       } catch (Exception e) {
       }

       try {
           mInstrumentation.callApplicationOnCreate(app);
       } catch (Exception e) {
       }
     }

     // Preload fonts resources
     FontsContract.setApplicationContextForResources(appContext);
     try {
         final ApplicationInfo info = getPackageManager().getApplicationInfo(
                            data.appInfo.packageName,
                            PackageManager.GET_META_DATA /*flags*/,
                            UserHandle.myUserId());
         if (info.metaData != null) {
             final int preloadedFontsResource = info.metaData.getInt(
                     ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
             if (preloadedFontsResource != 0) {
                 data.info.mResources.preloadFonts(preloadedFontsResource);
             }
         }
       } catch (RemoteException e) {
    }
}

從代碼可以得知,一個ActivityThread對象日川,即一個應(yīng)用的主線程中只會存在一個LoadedApk蔓腐、Instrumentation、Application等實例龄句,它們在一個應(yīng)用進程中被所有Activity共用回论。

接著調(diào)用ActivityStackSupervisor.attachApplicationLocked()在該進程啟動當前的目標Activity:

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 (!isFocusedStack(stack)) {
                 continue;
           }
           ActivityRecord hr = stack.topRunningActivityLocked();
           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) {
                   }
               }
           }
       }
   }
   if (!didSomething) {
      ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
   }
   return didSomething;
  }

首先得到當前任務(wù)棧頂端的Activity,它既是我們當前需要啟動的目標分歇。因為該Activity尚未啟動傀蓉,所以會去調(diào)用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),
             new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
             task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
             newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
   ...      
  return true;
}

app是一個ProcessRecord對象, app.thread 類型是 IApplicationThread职抡,因此app.thread是一個IApplicationThread的代理對象葬燎;它的實現(xiàn)是 ActivityThread 的內(nèi)部類 ApplicationThread,ApplicationThread繼承了 IApplicationThread.Stub。
app指的是傳入的要啟動的Activity的所在的應(yīng)用程序進程谱净,當前代碼邏輯運行在AMS所在的進程(SyetemServer進程)窑邦,
通過ApplicationThread來與應(yīng)用程序進程進行Binder通信,換句話說壕探,ApplicationThread是AMS所在進程(SyetemServer進程)和應(yīng)用程序進程的通信橋梁

app.thread調(diào)用scheduleLaunchActivity方法冈钦,通過Binder機制,會使ApplicationThread$scheduleLaunchActivity方法被調(diào)用李请。
于是瞧筛,基于Binder機制,實現(xiàn)了一次進程間的通信导盅,將啟動Activity的操作交給了ApplicationThread類较幌。

這樣調(diào)用queueOrSendMessage會往ActivityThread的消息隊列發(fā)送消息,消息的用途是BIND_APPLICATION白翻。

3. ActivityThread 啟動 Activity乍炉;

xref:/frameworks/base/core/java/android/app/ActivityThread.java

private class ApplicationThread extends IApplicationThread.Stub {
    ... 
    @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);

       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;
       r.persistentState = persistentState;

       r.pendingResults = pendingResults;
       r.pendingIntents = pendingNewIntents;

       r.startsNotResumed = notResumed;
       r.isForward = isForward;

       r.profilerInfo = profilerInfo;

       r.overrideConfig = overrideConfig;
       updatePendingConfiguration(curConfig);

       sendMessage(H.LAUNCH_ACTIVITY, r);
   }
}    
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);
}

首先將所有參數(shù)組裝成一個ActivityClientRecord, 然后通過mH成員變量發(fā)送msg出去,mH的類型是H嘁字,其實就是繼承于Handler類,是ActivityThread的內(nèi)部類杉畜,所以該消息最后由 H.handleMessage 來處理纪蜒。

private class H extends Handler {
    public static final int LAUNCH_ACTIVITY         = 100;
    public static final int PAUSE_ACTIVITY          = 101;
    
    ...
    
    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");
                   final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                   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;
               case PAUSE_ACTIVITY: {
                   Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                   SomeArgs args = (SomeArgs) msg.obj;
                   handlePauseActivity((IBinder) args.arg1, false,
                           (args.argi1 & USER_LEAVING) != 0, args.argi2,
                           (args.argi1 & DONT_REPORT) != 0, args.argi3);
                   maybeSnapshot();
                   Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
              } break;
              
              ...

通過getPackageInfoNoCheck方法獲得LoadedApk類型的對象并賦值給ActivityClientRecord 的成員變量packageInfo,
應(yīng)用程序進程要啟動Activity時需要將該Activity所屬的APK加載進來,而LoadedApk就是用來描述已加載的APK文件

首先會將AMS傳入的參數(shù)封裝成ActivityClientRecord對象此叠,然后調(diào)用ActivityThread::handleLaunchActivity():

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

    if (r.profilerInfo != null) {
        mProfiler.setProfiler(r.profilerInfo);
        mProfiler.startProfiling();
    }

   // Make sure we are running with the most recent config.
   handleConfigurationChanged(null, null);

   if (localLOGV) Slog.v(TAG, "Handling launch of " + r);

      // Initialize before creating the activity
      WindowManagerGlobal.initialize();

      Activity a = performLaunchActivity(r, customIntent);

      if (a != null) {
          r.createdConfig = new Configuration(mConfiguration);
          reportSizeConfigurations(r);
          Bundle oldState = r.state;
          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 {
                ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
      }
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    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);
   }

   ContextImpl appContext = createBaseContextForActivity(r);
   Activity activity = null;
   try {
       java.lang.ClassLoader cl = appContext.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 (activity != null) {
           CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
           Configuration config = new Configuration(mCompatConfiguration);
           if (r.overrideConfig != null) {
               config.updateFrom(r.overrideConfig);
           }
           
           Window window = null;
           if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
               window = r.mPendingRemoveWindow;
               r.mPendingRemoveWindow = null;
               r.mPendingRemoveWindowManager = null;
           }
           appContext.setOuterContext(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 (customIntent != null) {
                activity.mIntent = customIntent;
           }
           r.lastNonConfigurationInstances = null;
           checkAndBlockForNetworkAccess();
           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;
}

首先獲取ActivityInfo纯续, 然后通過activityinfo的信息去獲取LoadedApk, LoadedApk是描述一個APK文件信息的類灭袁;
然后創(chuàng)建啟動該 activity 的上下文 appContext猬错, 后面會用這個context去獲取classloader,為后面創(chuàng)建activity實例做準備茸歧;

Application app = r.packageInfo.makeApplication(false, mInstrumentation); 創(chuàng)建Application倦炒,
attach初始化activity,創(chuàng)建window對象软瞎,phoneWindow逢唤; 接下來調(diào)用 mInstrumentation 的callActivityOnCreate啟動activity

首先獲取當前Activity的全限定名,并通過ClassLoader來加載當前的Activity類涤浇,并創(chuàng)建該Activity的一個實例鳖藕;隨后會為當前應(yīng)用創(chuàng)建上下文對象及其他信息,并與該Activity關(guān)聯(lián)起來只锭;這部分內(nèi)容著恩,后續(xù)再分析,此處我們只關(guān)注Activity生命周期相關(guān)的內(nèi)容。接著:

Instrumentation.callActivityOnCreate()函數(shù)會根據(jù)當前Activity的實例去調(diào)用它的onCreate()函數(shù)
Activity.performStart()函數(shù)會去調(diào)用當前Activity的onStart()函數(shù)
會將當前當前啟動的Activity信息保存到ActivityThread::mActivities集合中

xref:/frameworks/base/core/java/android/app/Instrumentation.java

public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    restoreHasCurrentPermissionRequest(icicle);
    onCreate(icicle, persistentState);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喉誊,一起剝皮案震驚了整個濱河市邀摆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌裹驰,老刑警劉巖隧熙,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異幻林,居然都是意外死亡贞盯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門沪饺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躏敢,“玉大人,你說我怎么就攤上這事整葡【钔” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵醉者,是天一觀的道長玛追。 經(jīng)常有香客問我,道長俱萍,這世上最難降的妖魔是什么端壳? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮枪蘑,結(jié)果婚禮上损谦,老公的妹妹穿的比我還像新娘。我一直安慰自己岳颇,他們只是感情好照捡,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著话侧,像睡著了一般栗精。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瞻鹏,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天术羔,我揣著相機與錄音,去河邊找鬼乙漓。 笑死级历,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的叭披。 我是一名探鬼主播寥殖,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼玩讳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嚼贡?” 一聲冷哼從身側(cè)響起熏纯,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎粤策,沒想到半個月后樟澜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡叮盘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年秩贰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柔吼。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡毒费,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出愈魏,到底是詐尸還是另有隱情觅玻,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布培漏,位于F島的核電站溪厘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏牌柄。R本人自食惡果不足惜畸悬,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望友鼻。 院中可真熱鬧傻昙,春花似錦闺骚、人聲如沸彩扔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虫碉。三九已至,卻和暖如春胸梆,著一層夾襖步出監(jiān)牢的瞬間敦捧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工碰镜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留兢卵,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓绪颖,卻偏偏與公主長得像秽荤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容