ActivityMnagerService分析之啟動(dòng)一個(gè)Acitvity流程分析

AMS系列:
1、Activity生命周期、啟動(dòng)模式和隱式啟動(dòng)總結(jié)
2、ActivityManagerService啟動(dòng)分析
3、本文ActivityMnagerService分析之啟動(dòng)一個(gè)Acitvity

本文分析代碼基于N,首先ActivityManagerService的代碼是一個(gè)S/C結(jié)構(gòu),AIDL的通信方式,android端的各種服務(wù)端基本都是這種代碼結(jié)構(gòu)寫(xiě)的,建議不了解的讀者可以先看下筆者這篇文章PackageManagerService服務(wù)框架詳解和ActivityManagerService是類(lèi)似的,熟悉了AMS的代碼結(jié)構(gòu)閱讀起來(lái)心里面會(huì)更清晰

一、調(diào)用的過(guò)程

1.1 activity開(kāi)始start

首先是Activity#startActivity方法

@Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
//中間省略部分方法,這種常規(guī)套用java里面很常見(jiàn)
public void startActivityForResult(
            String who, Intent intent, int requestCode, @Nullable Bundle options) {
        Uri referrer = onProvideReferrer();
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, who,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, who, requestCode,
                ar.getResultCode(), ar.getResultData());
        }
        cancelInputsAndStartExitTransition(options);
    }

然后是Instrumentation#execStartActivity

 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
    int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
    ...
    }

1.2 Activity調(diào)用轉(zhuǎn)換到ActivityMnagerService

上面是一個(gè)普通的start流程,我們看到最后調(diào)用到ActivityManagerNative.getDefault().startActivity方法,那么我們來(lái)看一下這個(gè)getDefault獲得了什么
在ActivityManagerNative#getDefault

static public IActivityManager getDefault() {
        return gDefault.get();
    }
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
        // 獲得AMS的binder
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
        // 獲得AMS的代理類(lèi)ActivityManagerProxy
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

Actvity的相關(guān)方法最后的實(shí)現(xiàn)都是在AMS實(shí)現(xiàn)的,這里的ActivityManagerNative#getDefault方法其實(shí)是獲得了AMS的代理類(lèi),這里就是筆者一開(kāi)始說(shuō)的framework各類(lèi)服務(wù)的一個(gè)代碼框架,獲得了代理類(lèi)ActivityManagerProxy,就等于走到AMS的具體代碼里了。由于獲得了代理類(lèi),所以這個(gè)調(diào)用就等于調(diào)用到了ActivityManagerService#startActivity方法中了。
這里不能理解的讀者強(qiáng)烈建議閱讀PackageManagerService服務(wù)框架詳解

二、AMS服務(wù)端

2.1 AMS#startActivity

從ActivityManagerService#startActivity開(kāi)始

public int startActivity(IBinder whoThread, String callingPackage,
                Intent intent, String resolvedType, Bundle bOptions) {
        ...
            return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
                    resolvedType, null, null, null, null, 0, 0, null, null,
                    null, bOptions, false, callingUser, null, tr);
        }

2.2 ActivityStarter的調(diào)用

顯然調(diào)用順其自然的調(diào)用到了ActivityStarter#startActivityMayWait,這里引出了一個(gè)新的關(guān)鍵類(lèi)ActivityStarter

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, IActivityManager.WaitResult outResult, Configuration config,
            Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
        ...
    // Intent匹配搜索Component
        boolean componentSpecified = intent.getComponent() != null;
        ...
    // 這里調(diào)用到AppGlobals.getPackageManager().resolveIntent,通過(guò)PMS查詢(xún)把對(duì)應(yīng)的信息取出來(lái)
        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
        ...
    // 把上面rInfo得到的信息,匹配得到最終的ActivityInfo
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
        ...
        // 調(diào)用到startActivityLocked方法
            final ActivityRecord[] outRecord = new ActivityRecord[1];
            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);

            Binder.restoreCallingIdentity(origId);

            ...

        // 根據(jù)返回的res做最后處理
            if (outResult != null) {
                outResult.result = res;
                if (res == ActivityManager.START_SUCCESS) {
                    mSupervisor.mWaitingActivityLaunched.add(outResult);
                    do {
                        try {
                            mService.wait();
                        } catch (InterruptedException e) {
                        }
                    } while (outResult.result != START_TASK_TO_FRONT
                            && !outResult.timeout && outResult.who == null);
                    if (outResult.result == START_TASK_TO_FRONT) {
                        res = START_TASK_TO_FRONT;
                    }
                }
                if (res == START_TASK_TO_FRONT) {
                    ActivityRecord r = stack.topRunningActivityLocked();
                    if (r.nowVisible && r.state == RESUMED) {
                        outResult.timeout = false;
                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
                        outResult.totalTime = 0;
                        outResult.thisTime = 0;
                    } else {
                        outResult.thisTime = SystemClock.uptimeMillis();
                        mSupervisor.mWaitingActivityVisible.add(outResult);
                        do {
                            try {
                                mService.wait();  // 等待啟動(dòng)結(jié)果
                            } catch (InterruptedException e) {
                            }
                        } while (!outResult.timeout && outResult.who == null);
                    }
                }
            }

            final ActivityRecord launchedActivity = mReusedActivity != null
                    ? mReusedActivity : outRecord[0];
            mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
            return res;
        }
    }

startActivityMayWait流程如下:
1、從PMS中搜索匹配信息
2、startActivityLocked處理啟動(dòng)請(qǐng)求
3、根據(jù)返回的res做相應(yīng)處理

2.3 startActivityMayWait中的工作重點(diǎn)由startActivityLocked來(lái)啟動(dòng)

2.3.1 startActivityLocked

ActivityStarter#startActivityLocked方法(方法中提到的launchmode即啟動(dòng)模式讀者可以閱讀:Activity生命周期、啟動(dòng)模式和隱式啟動(dòng)總結(jié)里邊有講解,后續(xù)代碼也會(huì)有啟動(dòng)模式的處理)

 final 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) {
        int err = ActivityManager.START_SUCCESS;

    // 得到調(diào)用進(jìn)程的pid和uid
        ProcessRecord callerApp = null;
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                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;
            }
        }

        final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
        ...

    //sourceRecord用于描述啟動(dòng)目標(biāo)Activity的那個(gè)Activity,
        ActivityRecord sourceRecord = null;
    //resultRecord用于描述接收啟動(dòng)結(jié)果的Activity,即該Activity的onActivityResult
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                    "Will send result to " + resultTo + " " + sourceRecord);
            if (sourceRecord != null) {
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    resultRecord = sourceRecord;
                }
            }
        }
    
    // 獲得flag,這些flag跟launchmode類(lèi)似
        final int launchFlags = intent.getFlags();

        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
            // Transfer the result target from the source activity to the new
            // one being started, including any failures.
            if (requestCode >= 0) {
                ActivityOptions.abort(options);
                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
            }
            resultRecord = sourceRecord.resultTo;
            if (resultRecord != null && !resultRecord.isInStackLocked()) {
                resultRecord = null;
            }
            resultWho = sourceRecord.resultWho;
            requestCode = sourceRecord.requestCode;
            sourceRecord.resultTo = null;
            if (resultRecord != null) {
                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
            }
            if (sourceRecord.launchedFromUid == callingUid) {
                ...
                callingPackage = sourceRecord.launchedFromPackage;
            }
        }

    //下面這幾段err ==類(lèi)似的代碼 主要是匹配對(duì)應(yīng)信息,給予相應(yīng)的返回值
        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
            // We couldn't find a class that can handle the given Intent.
            // That's the end of that!
            err = ActivityManager.START_INTENT_NOT_RESOLVED;
        }

        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
            // We couldn't find the specific class specified in the Intent.
            // Also the end of the line.
            err = ActivityManager.START_CLASS_NOT_FOUND;
        }

        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
                && sourceRecord.task.voiceSession != null) {
            // If this activity is being launched as part of a voice session, we need
            // to ensure that it is safe to do so.  If the upcoming activity will also
            // be part of the voice session, we can only launch it if it has explicitly
            // said it supports the VOICE category, or it is a part of the calling app.
            if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
                try {
                    intent.addCategory(Intent.CATEGORY_VOICE);
                    if (!AppGlobals.getPackageManager().activitySupportsIntent(
                            intent.getComponent(), intent, resolvedType)) {
                        Slog.w(TAG,
                                "Activity being started in current voice task does not support voice: "
                                        + intent);
                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                    }
                } catch (RemoteException e) {
                    Slog.w(TAG, "Failure checking voice capabilities", e);
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            }
        }

        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
            // If the caller is starting a new voice session, just make sure the target
            // is actually allowing it to run this way.
            try {
                if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
                        intent, resolvedType)) {
                    Slog.w(TAG,
                            "Activity being started in new voice task does not support: "
                                    + intent);
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Failure checking voice capabilities", e);
                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
            }
        }

        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;

    // 如果start不成功直接返回
        if (err != START_SUCCESS) {
            if (resultRecord != null) {
                resultStack.sendActivityResultLocked(
                        -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
            }
            ActivityOptions.abort(options);
            return err;
        }

    // 檢查權(quán)限
        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
                resultRecord, resultStack, options);
        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                callingPid, resolvedType, aInfo.applicationInfo);

    // 給AMS整個(gè)監(jiān)聽(tīng),比如monkey測(cè)試就會(huì)調(diào)用這里獲得Activity運(yùn)行信息
        if (mService.mController != null) {
            try {
                // The Intent we give to the watcher has the extra data
                // stripped off, since it can contain private information.
                Intent watchIntent = intent.cloneFilter();
                abort |= !mService.mController.activityStarting(watchIntent,
                        aInfo.applicationInfo.packageName);
            } catch (RemoteException e) {
                mService.mController = null;
            }
        }

    // 省略一部份檢查代碼
        ...

        doPendingActivityLaunchesLocked(false);

        try {
            mService.mWindowManager.deferSurfaceLayout();
        // 處理本次Activity啟動(dòng)請(qǐng)求
            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                    true, options, inTask);
        } finally {
            mService.mWindowManager.continueSurfaceLayout();
        }
        postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
        return err;
    }

1、得到sourceRecord resultRecord
2、處理launchmode、返回值,都是一些標(biāo)記,沒(méi)有實(shí)質(zhì)操作
3、繼續(xù)調(diào)用啟動(dòng)startActivityUnchecked

2.3.2 startActivityUnchecked

我們接著startActivityUnchecked代碼分析

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
    // 初始化當(dāng)前傳遞進(jìn)來(lái)的信息
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor);
    // 這里是對(duì)flag處理,如:FLAG_ACTIVITY_NEW_TASK這一類(lèi)
        computeLaunchingTaskFlags();
    // 判斷打開(kāi)這個(gè)acitvity的task還存在否,如果不存在應(yīng)該new tast
        computeSourceStack();
    ...
    // 設(shè)置上面處理完后的flag
        mIntent.setFlags(mLaunchFlags);
    // 獲取當(dāng)前task是否已經(jīng)有activity了
        mReusedActivity = getReusableIntentActivity();

        final int preferredLaunchStackId =
                (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
    // 如果當(dāng)前已經(jīng)有activity了,那么啟動(dòng)的時(shí)候就會(huì)有各種LanchMode(啟動(dòng)模式)的處理,下面這if (mReusedActivity != null)一大段就是處理這個(gè)的
        if (mReusedActivity != null) {
            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
            // still needs to be a lock task mode violation since the task gets cleared out and
            // the device would otherwise leave the locked task.
            if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
                    (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
                mSupervisor.showLockTaskToast();
                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }

            if (mStartActivity.task == null) {
                mStartActivity.task = mReusedActivity.task;
            }
            if (mReusedActivity.task.intent == null) {
                // This task was started because of movement of the activity based on affinity...
                // Now that we are actually launching it, we can assign the base intent.
                mReusedActivity.task.setIntent(mStartActivity);
            }

            // This code path leads to delivering a new intent, we want to make sure we schedule it
            // as the first operation, in case the activity will be resumed as a result of later
            // operations.
            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                    || mLaunchSingleInstance || mLaunchSingleTask) {
                // In this situation we want to remove all activities from the task up to the one
                // being started. In most cases this means we are resetting the task to its initial
                // state.
                final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
                        mStartActivity, mLaunchFlags);
                if (top != null) {
                    if (top.frontOfTask) {
                        // Activity aliases may mean we use different intents for the top activity,
                        // so make sure the task now has the identity of the new intent.
                        top.task.setIntent(mStartActivity);
                    }
                    ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);

                    /// M: AMS log enhancement @{
                    if (DEBUG_TASKS) {
                        Slog.d(TAG, "ACT-AM_NEW_INTENT " + mStartActivity + " " + top.task);
                    }
                    /// @}

                    top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                            mStartActivity.launchedFromPackage);
                }
            }

            mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);

            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                // We don't need to start a new activity, and the client said not to do anything
                // if that is the case, so this is it!  And for paranoia, make sure we have
                // correctly resumed the top activity.
                resumeTargetStackIfNeeded();

                /// M: AMS log enhancement @{
                if (DEBUG_TASKS) {
                    Slog.d(TAG, "START_RETURN_INTENT_TO_CALLER");
                }
                /// @}

                return START_RETURN_INTENT_TO_CALLER;
            }
            setTaskFromIntentActivity(mReusedActivity);

            if (!mAddingToTask && mReuseTask == null) {
                // We didn't do anything...  but it was needed (a.k.a., client don't use that
                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
                resumeTargetStackIfNeeded();

                /// M: AMS log enhancement @{
                if (DEBUG_TASKS) {
                    Slog.d(TAG, "START_TASK_TO_FRONT");
                }
                /// @}

                return START_TASK_TO_FRONT;
            }
        }
    // 判斷當(dāng)前要打開(kāi)的activity的包名,如果為空說(shuō)明沒(méi)有這個(gè)class
        if (mStartActivity.packageName == null) {
            if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
                mStartActivity.resultTo.task.stack.sendActivityResultLocked(
                        -1, mStartActivity.resultTo, mStartActivity.resultWho,
                        mStartActivity.requestCode, RESULT_CANCELED, null);
            }
            ActivityOptions.abort(mOptions);

            /// M: AMS log enhancement @{
            if (DEBUG_TASKS) {
                Slog.d(TAG, "START_CLASS_NOT_FOUND");
            }
            /// @}

            return START_CLASS_NOT_FOUND;
        }

        // 檢查當(dāng)前要啟動(dòng)的activity是否已經(jīng)是已經(jīng)啟動(dòng)在當(dāng)前了,以確定是否需要啟動(dòng)
        final ActivityStack topStack = mSupervisor.mFocusedStack;
        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
        final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || mLaunchSingleTop || mLaunchSingleTask);
        if (dontStart) {
            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
            // For paranoia, make sure we have correctly resumed the top activity.
            topStack.mLastPausedActivity = null;
            if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();
            }
            ActivityOptions.abort(mOptions);
            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                // We don't need to start a new activity, and the client said not to do
                // anything if that is the case, so this is it!
                return START_RETURN_INTENT_TO_CALLER;
            }

            /// M: AMS log enhancement @{
            if (DEBUG_TASKS) {
                Slog.d(TAG, "ACT-AM_NEW_INTENT " + mStartActivity + " " + top.task);
            }
            /// @}

            top.deliverNewIntentLocked(
                    mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);

            // Don't use mStartActivity.task to show the toast. We're not starting a new activity
            // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
            mSupervisor.handleNonResizableTaskIfNeeded(
                    top.task, preferredLaunchStackId, topStack.mStackId);

            return START_DELIVERED_TO_TOP;
        }

        boolean newTask = false;
        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.task : null;

        // 下面這一段代碼處理了應(yīng)該以什么樣的task來(lái)運(yùn)行這個(gè)activity
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            setTaskFromReuseOrCreateNewTask(taskToAffiliate);

            if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
                /// M: ALPS02270164, Show lock task toast when in violation
                mSupervisor.showLockTaskToast();

                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
            if (!mMovedOtherTask) {
                updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
            }
        } else if (mSourceRecord != null) {
            if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
                /// M: ALPS02270164, Show lock task toast when in violation
                mSupervisor.showLockTaskToast();

                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }

            final int result = setTaskFromSourceRecord();
            if (result != START_SUCCESS) {
                return result;
            }
        } else if (mInTask != null) {
            // The caller is asking that the new activity be started in an explicit
            // task it has provided to us.
            if (mSupervisor.isLockTaskModeViolation(mInTask)) {
                /// M: ALPS02270164, Show lock task toast when in violation
                mSupervisor.showLockTaskToast();

                Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }

            final int result = setTaskFromInTask();
            if (result != START_SUCCESS) {
                return result;
            }
        } else {
            // This not being started from an existing activity, and not part of a new task...
            // just put it in the top task, though these days this case should never happen.
            setTaskToCurrentTopOrCreateNewTask();
        }

    // 權(quán)限檢查,比如uri打開(kāi)圖片,可能沒(méi)有sd讀權(quán)限
        mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
                mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);

        if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
            mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
        }
        ...
        ActivityStack.logStartActivity(
                EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
        ...

        mTargetStack.mLastPausedActivity = null;
    // 處理了打開(kāi)acitvity時(shí)中間應(yīng)該播放什么樣的動(dòng)畫(huà),和wms一起控制
        mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
        if (mDoResume) {
            if (!mLaunchTaskBehind) {
        // 設(shè)置啟動(dòng)activity焦點(diǎn)
                mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
            }
            final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                // 弱是一個(gè)已經(jīng)存在的acitvity,則恢復(fù)它onresume
                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                // Go ahead and tell window manager to execute app transition for this activity
                // since the app transition will not be triggered through the resume channel.
                mWindowManager.executeAppTransition();
            } else {
        // 啟動(dòng)走到了這里,接著分析
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
        // 把a(bǔ)ctivity更新到當(dāng)前task中
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

        mSupervisor.handleNonResizableTaskIfNeeded(
                mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);

        return START_SUCCESS;
    }

1、處理launchmode
2、以怎樣的task來(lái)啟動(dòng)activity
3、打開(kāi)動(dòng)畫(huà)處理
4、繼續(xù)走啟動(dòng)流程resumeFocusedStackTopActivityLocked
總結(jié)一句話(huà)就是在棧中添加好activity然后用resumeFocusedStackTopActivityLocked來(lái)啟動(dòng)它

2.3.3 resumeFocusedStackTopActivityLocked

boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
        // 待啟動(dòng)Activity對(duì)應(yīng)的Task為前臺(tái)Task時(shí),調(diào)用該Task對(duì)應(yīng)ActivityStack的resumeTopActivityUncheckedLocked函數(shù)
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
        // 否則只是調(diào)用當(dāng)前前臺(tái)棧的resumeTopActivityUncheckedLocked
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        }
        return false;
    }

代碼都是調(diào)用的resumeTopActivityUncheckedLocked
然后resumeTopActivityUncheckedLocked里邊是一個(gè)普通的嵌套,代碼又繼續(xù)走到resumeTopActivityInnerLocked
由于resumeTopActivityInnerLocked方法太長(zhǎng),我只截取了關(guān)鍵部分

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    // 啟動(dòng)的時(shí)候需要先pause之前的activity,最終也會(huì)走到startSpecificActivityLocked
    startPausingLocked(false, false, false, false);
    ...
    // 由此方法來(lái)啟動(dòng)
    mStackSupervisor.startSpecificActivityLocked(next, true, true);
    ...
}

這個(gè)方法就是這兩個(gè)大點(diǎn),省略的代碼都是圍繞這兩個(gè)點(diǎn)來(lái)處理
1、如果mResumedActivity不為空,則需要先暫停這個(gè)Activity。由startPausingLocked來(lái)完成
2、當(dāng)mResumedActivity為空時(shí),若待啟動(dòng)的Activity對(duì)應(yīng)的應(yīng)用存在,那么僅需要重新啟動(dòng)該Activity 否則,需要調(diào)用ActivityStackSupervisor的startSpecificActivityLocked函數(shù),啟動(dòng)整個(gè)進(jìn)程。
那么我們接著分析

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
    // 看要打開(kāi)的activity的app是否已經(jīng)運(yùn)行
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

    // 如果對(duì)應(yīng)進(jìn)程已經(jīng)存在,并向AMS注冊(cè)過(guò)
        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);
                }
        // 通知進(jìn)程啟動(dòng)目標(biāo)Activity
                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.
        }
    // 如果進(jìn)程不存在需要?jiǎng)?chuàng)建進(jìn)程來(lái)運(yùn)行
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

創(chuàng)建進(jìn)程就是走的啟動(dòng)一個(gè)應(yīng)用的流程了,這里先不分析,本文主要講一般的啟動(dòng)activity,那么我們看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);
    ...
}

這里的app.thread.scheduleLaunchActivity其實(shí)是一個(gè)binder的調(diào)用,app.thread就是IApplicationThread
下面列出的是實(shí)現(xiàn)方式,這塊兒不能理解的建議閱讀上面提到的PackageManagerService服務(wù)框架詳解

ApplicationThreadNative extends Binder implements IApplicationThread
ApplicationThread extends ApplicationThreadNative
public interface IApplicationThread extends IInterface {
    ...
    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) throws RemoteException;.
    ...
}

所以app.thread.scheduleLaunchActivity調(diào)用的等于是調(diào)用了 ApplicationThread#scheduleLaunchActivity

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

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

于是就調(diào)用到了handleLaunchActivity,handleLaunchActivity又內(nèi)套performLaunchActivity

2.3.4 performLaunchActivity

performLaunchActivity這里才是真正的創(chuàng)建的地方

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        // 這里開(kāi)始new Acitvity
            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);
            }
        } 
    ...

        try {
        // 創(chuàng)建 Application
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            ...

            if (activity != null) {
        // 創(chuàng)建Context
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
        // 創(chuàng)建 Configuration
                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;
                }
        // 調(diào)用acitvity的attach,將創(chuàng)建的這些對(duì)象關(guān)聯(lián)到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);

                ...

        return activity;
    }

2.4 服務(wù)端代碼總結(jié)

1、AMS接到客戶(hù)端的調(diào)用過(guò)后,開(kāi)始啟動(dòng),把啟動(dòng)的工作交給了ActivityStarter的startActivityMayWait
2、startActivityMayWait分了三步:
2.1>先從PMS中搜索匹配信息
2.2>然后startActivityUnchecked啟動(dòng)activity startActivityUnchecked:處理launchmode、以怎樣的task來(lái)啟動(dòng)activity、打開(kāi)動(dòng)畫(huà)處理、由resumeTopActivityInnerLocked分兩個(gè)方向走
2.2.1>>如果mResumedActivity不為空,則需要先暫停這個(gè)Activity。由startPausingLocked來(lái)完成
2.2.2>>當(dāng)mResumedActivity為空時(shí),若待啟動(dòng)的Activity對(duì)應(yīng)的應(yīng)用存在,那么僅需要重新啟動(dòng)該Activity 否則,需要調(diào)用ActivityStackSupervisor的startSpecificActivityLocked函數(shù),啟動(dòng)整個(gè)進(jìn)程。
2.2.2.1>>>通知進(jìn)程啟動(dòng)目標(biāo)Activity,此流程最后調(diào)用到performLaunchActivity直接創(chuàng)建了activity
2.2.2.2>>>如果進(jìn)程不存在需要?jiǎng)?chuàng)建進(jìn)程來(lái)運(yùn)行
2.3>最后處理返回值。

三、結(jié)束語(yǔ)

Activity是我們最常用的組件了,Activity整個(gè)流程走下來(lái)代碼還很復(fù)雜,概要下來(lái)主要流程還是比較清晰,具體細(xì)節(jié)處理這里筆者沒(méi)有太詳細(xì)的去分析了,畢竟代碼量很大,有碰到對(duì)應(yīng)問(wèn)題的時(shí)候,再去細(xì)細(xì)研究也不遲,主要是對(duì)整個(gè)流程得有一個(gè)認(rèn)知,這樣更利于理解Activity。處理對(duì)應(yīng)問(wèn)題的時(shí)候,也能快速定位相關(guān)代碼。

Read the fucking sources code!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容