深入理解Android 之 Activity啟動流程(Android 10)

maoqitian發表於2020-04-06

在進階Android的路上,瞭解理解一個應用根Activity啟動流程可以作為一個切入點,由此展開進階之路。平時我們開發的應用都是展示在Android系統桌面上,這個系統桌面其實也是一個Android應用,它叫Launcher。所以本文通過原始碼層面從Launcher呼叫ATMS,ATMS呼叫ApplicationThread,最後ActivityThread啟動Activity三個過程瞭解Activity啟動流程(文中原始碼基於Android 10 )。

Launcher到ActivityTaskManagerService

Launcher 呼叫 Activity

  • 至於Launcher如何載入展示應用程式到介面這裡先略過(與PMS相關),本文先關注Activity啟動過程。當我們點選系統桌面的應用圖示,直接響應的則是Launcher這個應用程式,會呼叫它的startActivitySafely方法

packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
            @Nullable String sourceContainer) {
        .....

        boolean success = super.startActivitySafely(v, intent, item, sourceContainer); // 1
        if (success && v instanceof BubbleTextView) {
            // This is set to the view that launched the activity that navigated the user away
            // from launcher. Since there is no callback for when the activity has finished
            // launching, enable the press state and keep this reference to reset the press
            // state when we return to launcher.
            BubbleTextView btv = (BubbleTextView) v;
            btv.setStayPressed(true);
            addOnResumeCallback(btv);
        }
        return success;
    }
複製程式碼
  • 通過以上原始碼,在註釋1呼叫的是父類的startActivitySafely方法,Launcher類本身就是Activity,它的父類為BaseDraggingActivity,接著看到它的startActivitySafely方法

packages/apps/Launcher3/src/com/android/launcher3/BaseDraggingActivity.java

public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
            @Nullable String sourceContainer) {
        .......

        // Prepare intent
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //1
        if (v != null) {
            intent.setSourceBounds(getViewBounds(v));
        }
        try {
            ......
            if (isShortcut) {
                // Shortcuts need some special checks due to legacy reasons.
                startShortcutIntentSafely(intent, optsBundle, item, sourceContainer);
            } else if (user == null || user.equals(Process.myUserHandle())) {
                // Could be launching some bookkeeping activity
                startActivity(intent, optsBundle);//2
                AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(),
                        Process.myUserHandle(), sourceContainer);
            } else {
                .......
            }
            getUserEventDispatcher().logAppLaunch(v, intent);
            getStatsLogManager().logAppLaunch(v, intent);
            return true;
        } catch (NullPointerException|ActivityNotFoundException|SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
        }
        return false;
    }
複製程式碼
  • 以上原始碼看到註釋1,設定啟動Activity的Flag為FLAG_ACTIVITY_NEW_TASK,設定這個Flag則Activity的啟動就會在新的任務棧中啟動,後面還會遇到它;接著看到註釋2,呼叫了startActivity的方法,顯然這就是呼叫了Activity類的startActivity方法。繼續探究Activity類的startActivity方法

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

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);//1
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }
複製程式碼
  • 有以上原始碼看到註釋1,Activity類的startActivity方法呼叫的是startActivityForResult方法,這個方法日常開發啟動Activity有引數回撥也會使用,這裡引數傳入-1,表明Launcher啟動Activity並不管它成功與否。接著看startActivityForResult方法

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

Activity mParent;

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) { //1
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);//2
            ......
        } else {
            ......
        }
    }
複製程式碼
  • 通過以上原始碼看到註釋1,mParent的宣告型別為Activity,當前還是正在起Activity,mParent == null成立,看到註釋2呼叫了Instrumentation類的execStartActivity方法,Instrumentation允許您監視系統與應用程式之間的所有互動(Instrumentation註釋:allowing you to monitor all of the interaction the system has with the application.),接著看到它的execStartActivity方法

Instrumentation 呼叫到ATMS

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

@UnsupportedAppUsage
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;//1
        ......
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityTaskManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options); //2
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
複製程式碼
  • 通過以上原始碼看到註釋1,這裡獲取了IApplicationThread,如果你瞭解Binder,第一反應就應該很清晰,目前處於Launcher應用程式程式,要啟動Activity則需要請求系統服務程式(SystemServer),而Android程式間通訊則可以使用Binder,而這裡實現方式為AIDL,它的實現類為ActivityThread的內部類ApplicationThread,而ApplicationThread作用則為應用程式程式和系統服務程式通訊的橋樑,後面還會繼續提到;接著看到註釋2,這裡呼叫ActivityTaskManager.getService則可以獲取ActivityTaskManagerService的代理物件,看看他的實現

frameworks/base/core/java/android/app/ActivityTaskManager.java

 public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
    }

    @UnsupportedAppUsage(trackingBug = 129726065)
    private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);//1
                    return IActivityTaskManager.Stub.asInterface(b); //2
                }
            };
複製程式碼
  • 由以上原始碼註釋1,通過ServiceManager來獲取遠端服務ActivityTaskManagerService,ServiceManager底層最終呼叫的還是c++層的ServiceManager,它是Binder的守護服務,通過它能夠獲取在Android系統啟動時註冊的系統服務,這其中就包含這裡提到的ATMS;接著回到註釋2建立 Launcher與 ATMS的連線,這樣回到execStartActivity方法,Launcher就通過呼叫ATMS的startActivity方法將啟動Activity的資料交給ATMS服務來處理了。

  • 為了更好理解,看看Launcher呼叫到ActivityTaskManagerService時序圖來對上面的步驟進行回顧

Launcher呼叫到ActivityTaskManagerService時序圖

ActivityTaskManagerService 呼叫ApplicationThread

ATMS處理啟動Activity請求

  • 通過上一小節,啟動應用程式Activity已經走到ActivityTaskManagerService中,如果你熟悉前以往版本的Android原始碼,你肯定會知道ActivityManagerService,而在Android 10 中則將AMS用於管理Activity及其容器(任務,堆疊,顯示等)的系統服務分離出來放到ATMS中,也許是谷歌不想讓AMS的程式碼越來越膨脹吧(Android 10中AMS程式碼有一萬九千行)。好了,接著看到ATMS的startActivity方法

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.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());//1
    }
複製程式碼
  • 由以上程式碼,繼續呼叫了startActivityAsUser方法,該方法多傳入了使用者的ID,接著會判斷是否有許可權呼叫,沒有許可權呼叫則丟擲異常,否則獲取使用者id用於後續程式間Binder通訊。接著繼續看startActivityAsUser方法

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

@Override
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);//1
    }

    int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        enforceNotIsolatedCaller("startActivityAsUser");

        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();//2

    }
複製程式碼
  • 由以上程式碼,註釋1呼叫了ATMS自己實現的startActivityAsUser方法,在註釋而2處構造了ActivityStarter,此類收集了用於確定將意圖和標誌如何轉換為活動以及關聯的任務和堆疊的所有邏輯,obtainStarter方法第二個引數代表啟動Activity的意圖,接著呼叫了execute方法,

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

int execute() {
        try {
            // TODO(b/64750076): Look into passing request directly to these methods to allow
            // for transactional diffs and preprocessing.
            if (mRequest.mayWait) { //1
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                        mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
                        mRequest.intent, mRequest.resolvedType,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                        mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                        mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);//2
            } 
          ......  
        } 
        .......
    }
複製程式碼
  • 由以上程式碼看到註釋1,前面構造ActivityStarter已經傳入了使用者id,所以這裡判斷條件成立,則繼續呼叫startActivityMayWait方法

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

private int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
            Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
            IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
            int userId, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup,
            PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
            ......

            final ActivityRecord[] outRecord = new ActivityRecord[1];//1
            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
                    allowBackgroundActivityStart);//2
          ......
            return res;
        }
    }
複製程式碼
  • 由以上程式碼,可以看到註釋1處建立了一個ActivityRecord陣列,ActivityRecord代表一個Activity,接著呼叫了startActivity方法,

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

   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,
            SafeActivityOptions options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
            PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
        mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
        int err = ActivityManager.START_SUCCESS;
        // Pull the optional Ephemeral Installer-only bundle out of the options early.
        final Bundle verificationBundle
                = options != null ? options.popAppVerificationBundle() : null;

        WindowProcessController callerApp = null;
        if (caller != null) {//1
            callerApp = mService.getProcessController(caller);//2
            if (callerApp != null) {
                callingPid = callerApp.getPid();
                callingUid = callerApp.mInfo.uid;
            } else {
                Slog.w(TAG, "Unable to find app for caller " + caller
                        + " (pid=" + callingPid + ") when starting: "
                        + intent.toString());
                err = ActivityManager.START_PERMISSION_DENIED;
            }
        }
       .......

        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r;//3
        }

       ......

        final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);//4
        .....
        return res;
    }
複製程式碼
  • 由以上程式碼,startActivity裡面有很多的邏輯程式碼,這裡只看一些重點的邏輯程式碼,主要做了兩個事情: (1)註釋1處判斷IApplicationThread是否為空,前面第一小節我們就已經提到過,它代表的就是Launcher程式的ApplicationThread,註釋2通過與即將要啟動的應用程式程式建立聯絡,應用程式程式的是fork到Zyote程式,這裡先不進行展開了,先專注Activity啟動流程。接著註釋3建立ActivityRecord代表即將要啟動的Activity,包含了Activity的所有資訊,並賦值給上一步驟中建立的ActivityRecord型別的outActivity,註釋4則繼續呼叫startActivity方法

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

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

        return result;
    }
複製程式碼
  • 由以上程式碼,註釋1處startActivity又呼叫了startActivityUnchecked方法

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

// Note: This method should only be called from {@link startActivity}.
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity, boolean restrictedBgActivity) {
        ......    
        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.getTaskRecord() : null;
        // Should this be considered a new task?
        int result = START_SUCCESS;
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { //1
            newTask = true;
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate); //2
        } 
        ........
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTaskRecord().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                
              mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
                mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
            } else {
                // If the target stack was not previously focusable (previous top running activity
                // on that stack was not visible) then any prior calls to move the stack to the
                // will not update the focused stack.  If starting the new activity now allows the
                // task stack to be focusable, then ensure that we now update the focused stack
                // accordingly.
                if (mTargetStack.isFocusable()
                        && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                mRootActivityContainer.resumeFocusedStacksTopActivities(
                        mTargetStack, mStartActivity, mOptions);//3
            }
        }
複製程式碼
  • 由上程式碼註釋1,在前面第一節Launcher部分中有提到過設定了Flag為FLAG_ACTIVITY_NEW_TASK,所以注意判斷條件成立,則呼叫setTaskFromReuseOrCreateNewTask,它內部會建立的TaskRecord(代表Activity的任務棧),並將傳入的TaskRecord物件設定給代表啟動的Activity的ActivityRecord,接著在註釋3呼叫了RootActivityContainer的resumeFocusedStacksTopActivities方法,RootActivityContainer 將一些東西從ActivityStackSupervisor中分離出來。目的是將其與RootWindowContainer合併,作為統一層次結構的一部分,接著看它的resumeFocusedStacksTopActivities方法

frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java

boolean resumeFocusedStacksTopActivities(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        ......

        boolean result = false;
        if (targetStack != null && (targetStack.isTopStackOnDisplay()
                || getTopDisplayFocusedStack() == targetStack)) { 
            result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);//1
        }

        .......

        return result;
    }
複製程式碼
  • 由以上程式碼註釋1處,又呼叫了ActivityStack的resumeTopActivityUncheckedLocked方法,ActivityStack應該算是任務棧的描述,它管理者一個應用的所有TaskRecord和他們的狀態,接著看到它的resumeTopActivityUncheckedLocked方法

frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java

//確保棧頂 activity 為Resume
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mInResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // 防止遞迴
            mInResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options); //1
            ........
        } finally {
            mInResumeTopActivity = false;
        }

        return result;
    }
複製程式碼
  • 由以上程式碼,在註釋1處接著又呼叫ActivityStack的resumeTopActivityInnerLocked方法

frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java

@GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    
    ....
    // Whoops, need to restart this activity!
            
            ........
       mStackSupervisor.startSpecificActivityLocked(next, true, true);//1
            ........
        
}
複製程式碼
  • 由以上程式碼看到註釋1,resumeTopActivityInnerLocked方法中邏輯非常多,這裡直接精簡到這一句關鍵程式碼,呼叫了ActivityStackSupervisor的startSpecificActivityLocked方法

ActivityStackSupervisor 啟動Activity

frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Activity應用程式程式是否已經準備好
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);

        boolean knownToBeDead = false;
        if (wpc != null && wpc.hasThread()) { //1
            try {
                realStartActivityLocked(r, wpc, andResume, checkConfig); //2
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity " 
                        + r.intent.getComponent().flattenToShortString(), e);
            }
        .......
        }

        .......
        try {
           .......
            // Post message to start process to avoid possible deadlock of calling into AMS with the
            // ATMS lock held.
            final Message msg = PooledLambda.obtainMessage(
                    ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
                    r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());//3
            mService.mH.sendMessage(msg);
        }
        ........
    }

複製程式碼
  • 如上程式碼所示註釋1,判斷要啟動的應用程式程式是否已經準備好,hasThread則是確定應用程式程式的IApplicationThread是否存在,如果存在則呼叫ActivityStackSupervisor的realStartActivityLocked方法啟動Activity;如果是第一次啟動,則應用程式程式沒有準備好,則會走到註釋3處啟動應用程式程式,本文先跳過,留到下篇文章再探究。接下來繼續看到realStartActivityLocked方法

frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {
           .......

                // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(
                        proc.getThread(), r.appToken);//1

                final DisplayContent dc = r.getDisplay().mDisplayContent;
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                        r.icicle, r.persistentState, results, newIntents,
                        dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
                                r.assistToken));//2

                // Set desired final state.
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // Schedule transaction.
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);//3

                .......

        return true;
    }
複製程式碼
  • 由以上程式碼註釋1處,建立了ClientTransaction物件,它是包含一系列訊息的容器,可以將其傳送到客戶端,這個客戶端就我們要啟動的應用程式Activity,註釋2處將前面一路傳遞進來的啟動Activity引數封裝成了LaunchActivityItem請求request物件,接著我們看到註釋3,這裡呼叫了ClientLifecycleManager的scheduleTransaction方法,它的初始化在AMTS構造方法中,並傳入了ClientTransaction引數,接著看到ClientLifecycleManager的scheduleTransaction方法

ClientLifecycleManager(ActivityThread)處理ClientTransaction

frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java

 void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();//1
        transaction.schedule();//2
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }
    }
複製程式碼
  • 到此,基本上已經比較清晰了,註釋1處獲取了要啟動的應用程式程式的IApplicationThread,上一步中建立ClientTransaction物件時已經將其賦值給ClientTransaction的變數mClient,隨後scheduleTransaction判斷是否支援程式間通訊;註釋二處則呼叫了ClientTransaction的schedule方法,

frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java

/** Target client. */
    private IApplicationThread mClient;
    
     /** Schedule the transaction after it was initialized. It will be send to client and all its
     * individual parts will be applied in the following sequence:
     * 1. The client calls {@link #preExecute(ClientTransactionHandler)}, which triggers all work
     *    that needs to be done before actually scheduling the transaction for callbacks and
     *    lifecycle state request.
     * 2. The transaction message is scheduled.
     * 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
     *    all callbacks and necessary lifecycle transitions.
     */
    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this); //1 
    }

複製程式碼
  • 通過以上程式碼,註釋1處mClient則代表要啟動的應用程式程式的IApplicationThread,而當前還處於ATMS服務的程式,也就是SystemServer程式,這時ATMS要與即將啟動的應用程式程式通訊則通過IApplicationThread來執行AIDL,IApplicationThread實現為ApplicationThread,它是ActivityThread的內部類,所以前面也說過ApplicationThread為程式間通訊的橋樑,註釋1處則相當於是IApplicationThread.scheduleTransaction,並將包含要啟動Activity資訊的ClientTransaction傳遞到了應用程式程式,下一節就從IApplicationThread講起。

  • 為了更好理解,看看AMTS呼叫到ApplicationThread時序圖來對上面的步驟進行回顧

AMTS呼叫到ApplicationThread時序圖

ActivityThread啟動Activity

ApplicationThread 處理程式間資料通訊

  • 接著上一節的內容,我們從ApplicationThread的scheduleTransaction方法開始

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

private class ApplicationThread extends IApplicationThread.Stub {
     @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);//1
        }
}
複製程式碼
  • 由以上程式碼,註釋1處呼叫了ActivityThread的scheduleTransaction方法,ActivityThread繼承了ClientTransactionHandler,scheduleTransaction在裡面實現

frameworks/base/core/java/android/app/ClientTransactionHandler.java

 /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
複製程式碼

ActivityThread.H 執行緒間訊息處理

  • 可以看到這裡傳送了一個Handler訊息,而ActivityThread.H則是ActivityThread的內部Handler,它是整個應用程式的主執行緒Handler,這裡為什麼需要切換執行緒呢?其原因為前面ATMS程式間通訊則是執行在Binder執行緒,而Android更新UI則需要在主執行緒,接著看到ActivityThread.H的訊息處理
 class H extends Handler {
 
  public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
            case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;//1
                    mTransactionExecutor.execute(transaction);//2
                    ......
                    break;
                    
             }       
}                    
複製程式碼

TransactionExecutor

  • 由以上程式碼,看到註釋1處,獲取了由ATMS傳遞過來的啟動Activity程式的資料,註釋2處呼叫了TransactionExecutor的來處理ClientTransaction的資料,接著看到它的execute方法

frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

public void execute(ClientTransaction transaction) {
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");

        .......

        executeCallbacks(transaction); //

        executeLifecycleState(transaction);
        mPendingActions.clear();
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
    }
複製程式碼
  • 由以上程式碼註釋1處接著呼叫了TransactionExecutor的executeCallbacks方法

frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

/** Cycle through all states requested by callbacks and execute them at proper times. */
    @VisibleForTesting
    public void executeCallbacks(ClientTransaction transaction) {
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
        if (callbacks == null || callbacks.isEmpty()) {
            // No callbacks to execute, return early.
            return;
        }
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callbacks in transaction");

        final IBinder token = transaction.getActivityToken();
        ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

        // In case when post-execution state of the last callback matches the final state requested
        // for the activity in this transaction, we won't do the last transition here and do it when
        // moving to final state instead (because it may contain additional parameters from server).
        final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
        final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
                : UNDEFINED;
        // Index of the last callback that requests some post-execution state.
        final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);

        final int size = callbacks.size();
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);//1
            if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
            final int postExecutionState = item.getPostExecutionState();
            final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
                    item.getPostExecutionState());
            if (closestPreExecutionState != UNDEFINED) {
                cycleToPath(r, closestPreExecutionState, transaction);
            }

            item.execute(mTransactionHandler, token, mPendingActions);//2
            ........
        }
    }
複製程式碼

LaunchActivityItem

  • 由以上程式碼註釋1處,獲取的ClientTransactionItem則為第二小節中提到過的LaunchActivityItem物件,它繼承了ClientTransactionItem,並儲存這需要啟動的Activity資料,接著看到註釋2 LaunchActivityItem的execute方法。

frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java

  @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client, mAssistToken);//1
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);//2
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
複製程式碼
  • 由以上程式碼,註釋1處恢復了要啟動的Activity的資料,ActivityClientRecord是ActivityThread的內部類,這裡的client為ClientTransactionHandler,而前面已經說過ActivityThread繼承ClientTransactionHandler,所以這裡的註釋2處呼叫的就是ActivityThread的handleLaunchActivity方法

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

 /**
     * Extended implementation of activity launch. Used when server requests a launch or relaunch.
     */
    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        .......

        final Activity a = performLaunchActivity(r, customIntent);//1

        .......

        return a;
    }
複製程式碼
  • 由以上程式碼註釋1處,繼續呼叫了ActivityThread的performLaunchActivity方法來啟動Activity,返回的也是Activity例項。所以performLaunchActivity方法才是啟動Activity例項的核心程式碼。

Core Activity Launch

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

/**  Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    
        ActivityInfo aInfo = r.activityInfo;//1
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);//2
        }

        ComponentName component = r.intent.getComponent();//3
        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);
        }

        //應用程式Context的建立
        ContextImpl appContext = createBaseContextForActivity(r);//4
        Activity activity = null;
        try {
        
            java.lang.ClassLoader cl = appContext.getClassLoader();
            //建立Activity的例項
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);//5
            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的建立
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);//6

           ......

            if (activity != null) {
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);
                // 通過Activity的 attach 方法將 context等各種資料與Activity繫結,初始化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,
                        r.assistToken); //7

                ......
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);//8
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ......
                r.activity = activity;
            }
            r.setState(ON_CREATE);

           .......
        }

        return activity;
    }
複製程式碼
  • 由以上程式碼,註釋1處獲取了前面儲存啟動應用程式資訊的ActivityClientRecord中的應用程式資訊,包括應用程式在清單檔案中註冊了哪些四大元件,啟動的根Activity是什麼,並在註釋2處通過getPackageInfo方法獲取LoadedApk描述對應Apk檔案資源,註釋3處的ComponentName類獲取則對應啟動Activity的包名和類名,註釋4處則生成了啟動應用程式的Base上下文環境Context,註釋5處通過註釋3獲取的類名,通過類載入器和Intent物件例項化了Activity物件,註釋6則根據註釋2處獲取Apk描述物件LoadedApk建立了應用程式的Application物件,並在makeApplication方法中呼叫了它的OnCreate方法,所以應用程式最新啟動的是Application才到根Activity,註釋7處則前面建立的Context、Application、Window物件與Activity關聯來初始化Activity,最後註釋8處還繼續呼叫了Instrumentation物件的callActivityOnCreate方法。接著往下看

Activity的 OnCreate方法呼叫

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

public void callActivityOnCreate(Activity activity, Bundle icicle,PersistableBundle persistentState) {
        prePerformCreate(activity); 
        activity.performCreate(icicle, persistentState);//1
        postPerformCreate(activity);
    }
複製程式碼
  • 由以上程式碼,註釋1處又呼叫了Activity的performCreate方法,繼續往下看

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

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        dispatchActivityPreCreated(icicle);
        mCanEnterPictureInPicture = true;
        restoreHasCurrentPermissionRequest(icicle);
        if (persistentState != null) {
            onCreate(icicle, persistentState);//1
        } else {
            onCreate(icicle);
        }
        .......
    }
複製程式碼
  • 最終,在已經例項初始化好的Activity呼叫它的performCreate方法中又掉用了onCreate方法(註釋1)。至此,也就是整個應用程式的Activity啟動過程我們已經走完了。
  • 為了更好理解,看看ActivityThread啟動Activity的時序圖來對上面的步驟進行回顧

ActivityThread啟動Activity的時序圖

最後

  • 通過本文,基本上將引用程式啟動根的Activity啟動流程走了一遍,但是其中還有一點沒說展開的就是應用程式程式的啟動過程,這一部分內容將通過後續文章繼續探究。。如果文章中有寫得不對的地方,歡迎在留言區留言大家一起討論,共同學習進步。如果覺得我的文章給予你幫助,也請給我一個喜歡和關注。

參考

About me

blog:

mail:

相關文章