Activity啟動流程源碼分析

前言

Launcher啟動app

launcher就是android桌面應(yīng)用程序。也是操作系統(tǒng)啟動有第一個(gè)app痰滋。同時(shí)作為其他app的入口。我們找到其源碼
android-6.0.0_r1\packages\apps\Launcher2
我們先看Manifest文件
找到app的入口Activity

        <activity
            android:name="com.android.launcher2.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:resumeWhilePausing="true"
            android:theme="@style/Theme"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="nosensor">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
            </intent-filter>
        </activity>

我們進(jìn)入到com.android.launcher2.Launcher
在進(jìn)入某個(gè)app的時(shí)候等恐,我們一般是點(diǎn)擊對應(yīng)的logo瓤湘。這里我們猜想Launcer里的點(diǎn)擊事件onClick方法應(yīng)該會被調(diào)用。搜索找到

        if (tag instanceof ShortcutInfo) {
            // Open shortcut
            final Intent intent = ((ShortcutInfo) tag).intent;
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1],
                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));

            boolean success = startActivitySafely(v, intent, tag);

            if (success && v instanceof BubbleTextView) {
                mWaitingForResume = (BubbleTextView) v;
                mWaitingForResume.setStayPressed(true);
            }
        } else if (tag instanceof FolderInfo) {
            if (v instanceof FolderIcon) {
                FolderIcon fi = (FolderIcon) v;
                handleFolderClick(fi);
            }
        }

這里只截取核心代碼碘饼,看到tag有ShortcutInfo熙兔、FolderInfo等類型。通過類名應(yīng)該可以理解艾恼,一個(gè)是app的入口住涉,一個(gè)是包含多個(gè)app的文件夾。這與我們使用手機(jī)的場景也是相符的钠绍。然后看到關(guān)鍵代碼boolean success = startActivitySafely(v, intent, tag);
進(jìn)入到該方法

    boolean startActivitySafely(View v, Intent intent, Object tag) {
        boolean success = false;
        try {
            success = startActivity(v, intent, tag);
        } catch (ActivityNotFoundException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
        }
        return success;
    }

這里就調(diào)用了startActivity(v, intent, tag) 舆声。Launcer是集成Activity的而改方法是Activity的方法。接下來就進(jìn)入到了我們熟悉的Activity的調(diào)用柳爽。

第一階段 Activity的startActivity ->AMS的startActivity

我們跟蹤到Activity的startActivity的方法媳握,最終調(diào)用到startActivityForResult

 Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);

這里最核心的一段代碼。這里又涉及一個(gè)類Instrumentation磷脯。這里先簡單的解釋一些這個(gè)類蛾找。

  • Instrumentation
    • 英文翻譯:儀表。
    • 在app進(jìn)程創(chuàng)建后,ActivityThread的main執(zhí)行后被創(chuàng)建赵誓。
    • 作用:
      • 用于控制Activity打毛,監(jiān)控應(yīng)用程序和系統(tǒng)的交互。
      • 啟動Activity的入口
      • 調(diào)用Activity的生命周期方法俩功。
      • 每個(gè)app進(jìn)程有且僅有一個(gè)Instrumentation對象
        這里先簡單認(rèn)知一下隘冲,不用過多的糾結(jié)“笮郏可以到它的大多數(shù)方法都和Activity的生命周期方法相關(guān)展辞。也就是Activity的生命周期方法可以由它來調(diào)用。
        我們繼續(xù)跟進(jìn)Instrumentation的execStartActivity方法万牺。我們截取核心代碼
int result = ActivityManagerNative.getDefault()
    .startActivity(whoThread, who.getBasePackageName(), intent,
            intent.resolveTypeIfNeeded(who.getContentResolver()),
            token, target != null ? target.mEmbeddedID : null,
            requestCode, 0, null, options);

這里就開始和AMS有關(guān)系了罗珍。我們先看到ActivityManagerNative.getDefault()得到的是IActivityManager的實(shí)現(xiàn)洽腺。

    static public IActivityManager getDefault() {
        return gDefault.get();
    }

繼續(xù)看到gDefault

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};

這里是一個(gè)單例的實(shí)現(xiàn)。gDefault.get()時(shí)候會調(diào)用create()得到IActivityManager的實(shí)現(xiàn)覆旱。而IActivityManager的實(shí)現(xiàn)是什么呢蘸朋。我們具體看到create()的代碼實(shí)現(xiàn)
IBinder b = ServiceManager.getService("activity");
這里涉及到了Binder機(jī)制。android中IPC通信使用的Binder機(jī)制扣唱。這里又出現(xiàn)類一個(gè)重要的類ServiceMananger藕坯。我們先做簡單的介紹:

ServiceMananger:
android中比較重要的一個(gè)進(jìn)程它是在init進(jìn)程啟動之后啟動,從名字上就可以看出來它是用來管理系統(tǒng)中的service噪沙。比如:InputMethodService炼彪、ActivityManagerService等。系統(tǒng)的services會把自己的信息注冊到ServiceManager正歼。同時(shí)當(dāng)需要獲取系統(tǒng)的Services也是通過ServiceManager來獲取辐马。這里我們只介紹它是干什么用的。至于具體的實(shí)現(xiàn)這里就不做展開局义,否則就偏離我們的主題了喜爷。

回到主題,這里通過ServiceManager獲取到了遠(yuǎn)程service的Binder接口萄唇。然后調(diào)用asInterface(b)獲取到IActivityManager 的實(shí)現(xiàn)檩帐。
進(jìn)入到asInterface

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

這里創(chuàng)建了一個(gè)ActivityManagerProxy對象。如果已創(chuàng)建則直接返回另萤。這里又出現(xiàn)一個(gè)類ActivityManagerProxy

ActivityManagerProxy

  • 實(shí)現(xiàn)了IActivityManager 的接口
  • ActivityManagerNative的內(nèi)部類
  • 通過構(gòu)造方法傳入遠(yuǎn)程ams的binder引用湃密。同時(shí)從命名看到這是一個(gè)代理類。代理ams.

回到Instrumentation的execStartActivity調(diào)用的ActivityManagerNative.getDefault() .startActivity實(shí)際上調(diào)用到了ActivityManagerProxy的startActivity

    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

這里主要是講參數(shù)進(jìn)行組包成Parcel類型仲墨。然后調(diào)用Binder的transact方法

mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);

繼續(xù)進(jìn)入到Binder的transact

    public final boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
        if (data != null) {
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }

最終會調(diào)用到onTransact 我們?nèi)ms中看onTransact的實(shí)現(xiàn)勾缭。代碼不多揍障,最后調(diào)用到了return super.onTransact(code, data, reply, flags);目养。我們?nèi)タ匆幌耡ms的繼承關(guān)系,發(fā)現(xiàn)它是集成ActivityManagerNative毒嫡。這就比較清晰了癌蚁,我們進(jìn)入到AMN查看onTransact

    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        case START_ACTIVITY_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            String callingPackage = data.readString();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            IBinder resultTo = data.readStrongBinder();
            String resultWho = data.readString();
            int requestCode = data.readInt();
            int startFlags = data.readInt();
            ProfilerInfo profilerInfo = data.readInt() != 0
                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
            Bundle options = data.readInt() != 0
                    ? Bundle.CREATOR.createFromParcel(data) : null;
            int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }
       ...
}

這里我們看到對Parcel 類型的data進(jìn)行了解包。然后調(diào)用ams的startActivity方法兜畸。最終進(jìn)入到了AMS的startActivity努释。

第二階段 AMS startActivity

這里的代碼就非常的多了。估計(jì)很多人都是敗在這里咬摇,但我們只看到核心邏輯部分伐蒂。
直接上代碼

@Override
public int startActivity(IBinder whoThread, String callingPackage,
        Intent intent, String resolvedType, Bundle options) {
    checkCaller();

    int callingUser = UserHandle.getCallingUserId();
    TaskRecord tr;
    IApplicationThread appThread;
    synchronized (ActivityManagerService.this) {
        tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
        if (tr == null) {
            throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
        }
        appThread = ApplicationThreadNative.asInterface(whoThread);
        if (appThread == null) {
            throw new IllegalArgumentException("Bad app thread " + appThread);
        }
    }
    return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,
            resolvedType, null, null, null, null, 0, 0, null, null,
            null, options, false, callingUser, null, tr);
}

我們看到最后一句核心調(diào)用mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent, resolvedType, null, null, null, null, 0, 0, null, null, null, options, false, callingUser, null, tr)
這里又出現(xiàn)了一個(gè)類ActivityStackSuperbisor。

ActivityStackSuperbisor

  • 監(jiān)督人肛鹏,指導(dǎo)人的意思逸邦。這里代表ActivityStack的管理類恩沛。
  • ActivityStack內(nèi)有多個(gè)TaskRecord,TaskRecord有多個(gè)ActivityRecord缕减。每次新啟動一個(gè)Activity會創(chuàng)建一個(gè)ActivityRecord

先提前透露下整個(gè)startActivity的調(diào)用主要就是在ActivityStackSupervisor雷客、ActivityStack、ActivityThread桥狡、ApplicationThread這幾個(gè)類中間進(jìn)行方法調(diào)用搅裙。
我們回到代碼,進(jìn)入到ActivityStackSupervisor的startActivityMayWait方法

    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 config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        boolean componentSpecified = intent.getComponent() != null;

        // Don't modify the client's object!
        intent = new Intent(intent);

        // Collect information about the target of the Intent.
        ActivityInfo aInfo =
                resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);

        ActivityContainer container = (ActivityContainer)iContainer;
        synchronized (mService) {
            if (container != null && container.mParentActivity != null &&
                    container.mParentActivity.state != RESUMED) {
                // Cannot start a child activity if the parent is not resumed.
                return ActivityManager.START_CANCELED;
            }
            final int realCallingPid = Binder.getCallingPid();
            final int realCallingUid = Binder.getCallingUid();
            int callingPid;
            if (callingUid >= 0) {
                callingPid = -1;
            } else if (caller == null) {
                callingPid = realCallingPid;
                callingUid = realCallingUid;
            } else {
                callingPid = callingUid = -1;
            }

            final ActivityStack stack;
            if (container == null || container.mStack.isOnHomeDisplay()) {
                stack = mFocusedStack;
            } else {
                stack = container.mStack;
            }
            stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                    "Starting activity when config will change = " + stack.mConfigWillChange);

            final long origId = Binder.clearCallingIdentity();

      ...省略部分代碼

            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);
      ...省略部分代碼
}

方法內(nèi)部

  1. 解析intent得到ActivityInfo
  2. 做一些系統(tǒng)的判斷裹芝,Uid和Pid的判斷
  3. 調(diào)用到startActivityLocked

進(jìn)入到startActivityLocked

final int startActivityLocked(IApplicationThread caller,
        Intent intent, String resolvedType, ActivityInfo aInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode,
        int callingPid, int callingUid, String callingPackage,
        int realCallingPid, int realCallingUid, int startFlags, Bundle options,
        boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
        ActivityContainer container, TaskRecord inTask) {
    int err = ActivityManager.START_SUCCESS;

    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 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;

    ...省略部分代碼

    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
            intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
            requestCode, componentSpecified, voiceSession != null, this, container, options);
    if (outActivity != null) {
        outActivity[0] = r;
    }

    
    ...省略部分代碼
    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, true, options, inTask);

    if (err < 0) {
        // If someone asked to have the keyguard dismissed on the next
        // activity start, but we are not actually doing an activity
        // switch...  just dismiss the keyguard now, because we
        // probably want to see whatever is behind it.
        notifyActivityDrawnForKeyguard();
    }
    return err;
}
  1. 獲取調(diào)用者的ProcessRecord
  2. 創(chuàng)建ActivityRecord對象部逮,每個(gè)ActivityRecord對應(yīng)一個(gè)Activity實(shí)例
  3. 調(diào)用startActivityUncheckedLocked

進(jìn)入到startActivityUncheckedLocked這個(gè)代碼也是又臭又長,我們截取關(guān)鍵代碼

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
        boolean doResume, Bundle options, TaskRecord inTask) {
    final Intent intent = r.intent;
    final int callingUid = r.launchedFromUid;

    // In some flows in to this function, we retrieve the task record and hold on to it
    // without a lock before calling back in to here...  so the task at this point may
    // not actually be in recents.  Check for that, and if it isn't in recents just
    // consider it invalid.
    if (inTask != null && !inTask.inRecents) {
        Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
        inTask = null;
    }

    final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
    final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
    final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;

    int launchFlags = intent.getFlags();
    if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
            (launchSingleInstance || launchSingleTask)) {
        // We have a conflict between the Intent and the Activity manifest, manifest wins.
        Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
                "\"singleInstance\" or \"singleTask\"");
        launchFlags &=
                ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
    } else {
        switch (r.info.documentLaunchMode) {
            case ActivityInfo.DOCUMENT_LAUNCH_NONE:
                break;
            case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                break;
            case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                break;
            case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
                launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
                break;
        }
    }

    final boolean launchTaskBehind = r.mLaunchTaskBehind
            && !launchSingleTask && !launchSingleInstance
            && (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;

    if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
            && r.resultTo.task.stack != null) {
        // For whatever reason this activity is being launched into a new
        // task...  yet the caller has requested a result back.  Well, that
        // is pretty messed up, so instead immediately send back a cancel
        // and let the new task continue launched as normal without a
        // dependency on its originator.
        Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
        r.resultTo.task.stack.sendActivityResultLocked(-1,
                r.resultTo, r.resultWho, r.requestCode,
                Activity.RESULT_CANCELED, null);
        r.resultTo = null;
    }

    if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    }

    // If we are actually going to launch in to a new task, there are some cases where
    // we further want to do multiple task.
    if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        if (launchTaskBehind
                || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) {
            launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
        }
    }

    // We'll invoke onUserLeaving before onPause only if the launching
    // activity did not explicitly state that this is an automated launch.
    mUserLeaving = (launchFlags & Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
    if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
            "startActivity() => mUserLeaving=" + mUserLeaving);

    // If the caller has asked not to resume at this point, we make note
    // of this in the record so that we can skip it when trying to find
    // the top running activity.
    if (!doResume) {
        r.delayedResume = true;
    }

    ActivityRecord notTop =
            (launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;

    // If the onlyIfNeeded flag is set, then we can do this if the activity
    // being launched is the same as the one making the call...  or, as
    // a special case, if we do not know the caller then we count the
    // current top activity as the caller.
    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
        ActivityRecord checkedCaller = sourceRecord;
        if (checkedCaller == null) {
            checkedCaller = mFocusedStack.topRunningNonDelayedActivityLocked(notTop);
        }
        if (!checkedCaller.realActivity.equals(r.realActivity)) {
            // Caller is not the same as launcher, so always needed.
            startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
        }
    }

    boolean addingToTask = false;
    TaskRecord reuseTask = null;
    
    ...省略部分代碼
    
    ActivityInfo newTaskInfo = null;
    Intent newTaskIntent = null;
    ActivityStack sourceStack;
    if (sourceRecord != null) {
        if (sourceRecord.finishing) {
            // If the source is finishing, we can't further count it as our source.  This
            // is because the task it is associated with may now be empty and on its way out,
            // so we don't want to blindly throw it in to that task.  Instead we will take
            // the NEW_TASK flow and try to find a task for it. But save the task information
            // so it can be used when creating the new task.
            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                Slog.w(TAG, "startActivity called from finishing " + sourceRecord
                        + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
                newTaskInfo = sourceRecord.info;
                newTaskIntent = sourceRecord.task.intent;
            }
            sourceRecord = null;
            sourceStack = null;
        } else {
            sourceStack = sourceRecord.task.stack;
        }
    } else {
        sourceStack = null;
    }

    boolean movedHome = false;
    ActivityStack targetStack;

    intent.setFlags(launchFlags);
    final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0;

    ...省略部分代碼

    TaskRecord taskToAffiliate = launchTaskBehind && sourceRecord != null ?
            sourceRecord.task : null;

    // Should this be considered a new task?
    if (r.resultTo == null && inTask == null && !addingToTask
            && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        targetStack = computeStackFocus(r, newTask);
        targetStack.moveToFront("startingNewTask");

        if (reuseTask == null) {
            r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                    newTaskInfo != null ? newTaskInfo : r.info,
                    newTaskIntent != null ? newTaskIntent : intent,
                    voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
                    taskToAffiliate);
            if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                    "Starting new activity " + r + " in new task " + r.task);
        }
        
    ...省略部分代碼
    targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
    if (!launchTaskBehind) {
        // Don't set focus on an activity that's going to the back.
        mService.setFocusedActivityLocked(r, "startedActivity");
    }
    return ActivityManager.START_SUCCESS;
}
  1. 設(shè)置啟動方式的標(biāo)示launchMode
  2. 獲取StackRecord局雄。如果需要?jiǎng)?chuàng)建則在r.setTask(targetStack.createTaskRecord(getNextTaskId(), newTaskInfo != null ? newTaskInfo : r.info, newTaskIntent != null ? newTaskIntent : intent, voiceSession, voiceInteractor, !launchTaskBehind /* toTop */), taskToAffiliate);這里創(chuàng)建
    最后來到ActivityStack的startActivityLocked方法
    final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        TaskRecord rTask = r.task;
        final int taskId = rTask.taskId;
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
            // Last activity in task had been removed or ActivityManagerService is reusing task.
            // Insert or replace.
            // Might not even be in.
            insertTaskAtTop(rTask, r);
            mWindowManager.moveTaskToTop(taskId);
        }
        TaskRecord task = null;
        ...省略部分代碼
        // Place a new activity at top of stack, so it is next to interact
        // with the user.

        // If we are not placing the new activity frontmost, we do not want
        // to deliver the onUserLeaving callback to the actual frontmost
        // activity
        if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
            mStackSupervisor.mUserLeaving = false;
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "startActivity() behind front, mUserLeaving=false");
        }

        task = r.task;

        // Slot the activity into the history stack and proceed
        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
                new RuntimeException("here").fillInStackTrace());
        task.addActivityToTop(r);
        task.setFrontOfTask();

        ...省略部分代碼

        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

  1. 將ActivityRecord添加到TaskRecord中
  2. 調(diào)用TaskRecord的setFrontOfTask().
          /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
    final void setFrontOfTask() {
        boolean foundFront = false;
        final int numActivities = mActivities.size();
        for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
            final ActivityRecord r = mActivities.get(activityNdx);
            if (foundFront || r.finishing) {
                r.frontOfTask = false;
            } else {
                r.frontOfTask = true;
                // Set frontOfTask false for every following activity.
                foundFront = true;
            }
        }
        if (!foundFront && numActivities > 0) {
            // All activities of this task are finishing. As we ought to have a frontOfTask
            // activity, make the bottom activity front.
            mActivities.get(0).frontOfTask = true;
        }
    }
    
    將當(dāng)前TaskRecord中的第一個(gè)ActivityRecord設(shè)置為true甥啄。其余設(shè)置為false
  3. 有調(diào)回到ActivityStackSupervisor的resumeTopActivitiesLocked
    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = mFocusedStack;
        }
        // Do targetStack first.
        boolean result = false;
        if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (stack == targetStack) {
                    // Already started above.
                    continue;
                }
                if (isFrontStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }

1 判斷調(diào)用的TaskRecord和要啟動的Activity的ActivityStack是否一樣如果是一樣的就進(jìn)入到對應(yīng)ActivityStack的resumeTopActivityLocked。否則去遍歷找到對應(yīng)的

繼續(xù)進(jìn)入到resumeTopActivityLocked

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
    if (mStackSupervisor.inResumeTopActivity) {
        // Don't even start recursing.
        return false;
    }

    boolean result = false;
    try {
        // Protect against recursion.
        mStackSupervisor.inResumeTopActivity = true;
        if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
            mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
            mService.updateSleepIfNeededLocked();
        }
        result = resumeTopActivityInnerLocked(prev, options);
    } finally {
        mStackSupervisor.inResumeTopActivity = false;
    }
    return result;
}

隨后調(diào)用到resumeTopActivityInnerLocked

   private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
        ...省略部分代碼
        ActivityRecord parent = mActivityContainer.mParentActivity;

        cancelInitializingActivities();

        // Find the first activity that is not finishing.
        final ActivityRecord next = topRunningActivityLocked(null);


        ...省略部分代碼

        // We are starting up the next activity, so tell the window manager
        // that the previous one will be hidden soon.  This way it can know
        // to ignore it when computing the desired screen orientation.
        boolean anim = true;
        if (prev != null) {
            if (prev.finishing) {
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                        "Prepare close transition: prev=" + prev);
                if (mNoAnimActivities.contains(prev)) {
                    anim = false;
                    mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
                } else {
                    mWindowManager.prepareAppTransition(prev.task == next.task
                            ? AppTransition.TRANSIT_ACTIVITY_CLOSE
                            : AppTransition.TRANSIT_TASK_CLOSE, false);
                }
                mWindowManager.setAppWillBeHidden(prev.appToken);
                mWindowManager.setAppVisibility(prev.appToken, false);
            } else {
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                        "Prepare open transition: prev=" + prev);
                if (mNoAnimActivities.contains(next)) {
                    anim = false;
                    mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
                } else {
                    mWindowManager.prepareAppTransition(prev.task == next.task
                            ? AppTransition.TRANSIT_ACTIVITY_OPEN
                            : next.mLaunchTaskBehind
                                    ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
                                    : AppTransition.TRANSIT_TASK_OPEN, false);
                }
            }
            if (false) {
                mWindowManager.setAppWillBeHidden(prev.appToken);
                mWindowManager.setAppVisibility(prev.appToken, false);
            }
        } else {
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
            if (mNoAnimActivities.contains(next)) {
                anim = false;
                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
            } else {
                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
            }
        }
        ...省略部分代碼
        ActivityStack lastStack = mStackSupervisor.getLastStack();
        if (next.app != null && next.app.thread != null) {
            ...省略部分代碼
    
        } else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    mWindowManager.setAppStartingWindow(
                            next.appToken, next.packageName, next.theme,
                            mService.compatibilityInfoForPackageLocked(
                                    next.info.applicationInfo),
                            next.nonLocalizedLabel,
                            next.labelRes, next.icon, next.logo, next.windowFlags,
                            null, true);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }
  1. 做頁面切換的準(zhǔn)備工作
  2. 調(diào)用到startSpecificActivityLocked

進(jìn)入到startSpecificActivityLocked

    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.task.stack.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);
    }

這個(gè)方法就比較重要了炬搭。首先會判斷當(dāng)前app的進(jìn)程是否已經(jīng)啟動蜈漓,如果沒有啟動測調(diào)用mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true);通過ams啟動進(jìn)程。如果已經(jīng)啟動則調(diào)用realStartActivityLocked(r, app, andResume, checkConfig)開始真正的啟動Activity

進(jìn)入到realStartActivityLocked中我們截取關(guān)鍵代碼

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

這里調(diào)用了ApplicationThread的scheduleLaunchActivity開始啟動Activity

真正開始啟動Activity

進(jìn)程的啟動這里就不做介紹宫盔,后面會專門寫一篇進(jìn)程啟動的源碼解讀融虽,們現(xiàn)在討論進(jìn)程已存在的情況下啟動Activity。
ActivityStackSupervisor的realStartActivityLocked

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
        System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
        new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
        task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
        newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

我們看到app.thread是IApplicationThread灼芭。其實(shí)現(xiàn)是ApplicationThread有额。ActivityThread的內(nèi)部類。
進(jìn)入到方法的內(nèi)部

// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
@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);
}
  • 創(chuàng)建ActivityClientRecord對象彼绷,并設(shè)置相關(guān)的信息巍佑。
  • 通過Handler把ActivityClientRecord發(fā)送給ActivityThread去處理。

我們進(jìn)入到ActivityThread的Handler處理方法

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);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
...省略部分代碼
  • 設(shè)置ActivityClientRecord的packageInfo
  • 調(diào)用handleLaunchActivity

進(jìn)入到handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    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);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed);

這里有兩段核心的代碼

  • Activity a = performLaunchActivity(r, customIntent);主要回調(diào)到Activity的onCreate寄悯、onStart等生命周期方法
  •                   !r.activity.mFinished && !r.startsNotResumed);```主要回調(diào)到onResume方法
    
    

我們先進(jìn)入到performLaunchActivity(r, customIntent)

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...省略部分代碼

    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ...省略部分代碼
    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

         ...省略部分代碼

        if (activity != null) {
            Context appContext = createBaseContextForActivity(r, activity);
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                    + r.activityInfo.name + " with config " + config);
            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);

            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            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);
        ...省略部分代碼

    return activity;
}
  • 創(chuàng)建Activity對象萤衰,我們在介紹Instrumentation中有提到。
  • 得到Application對象
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    LoadedApk中:
     public Application makeApplication(boolean forceDefaultAppClass,
             Instrumentation instrumentation) {
         if (mApplication != null) {
             return mApplication;
         }
    
         Application app = null;
    
         String appClass = mApplicationInfo.className;
         if (forceDefaultAppClass || (appClass == null)) {
             appClass = "android.app.Application";
         }
    
         try {
             java.lang.ClassLoader cl = getClassLoader();
             if (!mPackageName.equals("android")) {
                 initializeJavaContextClassLoader();
             }
             ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
             app = mActivityThread.mInstrumentation.newApplication(
                     cl, appClass, appContext);
             appContext.setOuterContext(app);
         } catch (Exception e) {
             if (!mActivityThread.mInstrumentation.onException(app, e)) {
                 throw new RuntimeException(
                     "Unable to instantiate application " + appClass
                     + ": " + e.toString(), e);
             }
         }
         mActivityThread.mAllApplications.add(app);
         mApplication = app;
    
         if (instrumentation != null) {
             try {
                 instrumentation.callApplicationOnCreate(app);
             } catch (Exception e) {
                 if (!instrumentation.onException(app, e)) {
                     throw new RuntimeException(
                         "Unable to create application " + app.getClass().getName()
                         + ": " + e.toString(), e);
                 }
             }
         }
    
         // Rewrite the R 'constants' for all library apks.
         SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
                 .getAssignedPackageIdentifiers();
         final int N = packageIdentifiers.size();
         for (int i = 0; i < N; i++) {
             final int id = packageIdentifiers.keyAt(i);
             if (id == 0x01 || id == 0x7f) {
                 continue;
             }
    
             rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
         }
    
         return app;
     }
    
    這里如果Application已存在猜旬,則直接返回脆栋。否則先創(chuàng)建ContextImpl,然后再創(chuàng)建Application洒擦,這里也知道了Application的getContext得到的Context就是在這里創(chuàng)建的椿争。
  • 創(chuàng)建Activity的Context Context appContext = createBaseContextForActivity(r, activity);
  • 調(diào)用Activity的attach()方法。這也是一個(gè)很重要的方法熟嫩。
  • 調(diào)用到mInstrumentation.callActivityOnCreate(activity, r.state);而Instrumentation則調(diào)用到了Activity的onCreate方法秦踪。
  • 調(diào)用Activity的performStart。activity.performStart();而方法的內(nèi)部會調(diào)用到mInstrumentation.callActivityOnStart(this);最后回調(diào)到Activity的onStart().
  • 調(diào)用mInstrumentation.callActivityOnPostCreate(activity, r.state);

我們回到handleLaunchActivity方法執(zhí)行完Activity a = performLaunchActivity(r, customIntent);后就調(diào)用到

handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

繼續(xù)進(jìn)入

final void handleResumeActivity(IBinder token,
        boolean clearHide, boolean isForward, boolean reallyResume) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

    // TODO Push resumeArgs into the activity for consideration
    ActivityClientRecord r = performResumeActivity(token, clearHide);

    if (r != null) {
        final Activity a = r.activity;

        if (localLOGV) Slog.v(
            TAG, "Resume " + r + " started activity: " +
            a.mStartedActivity + ", hideForNow: " + r.hideForNow
            + ", finished: " + a.mFinished);

        final int forwardBit = isForward ?
                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

        // If the window hasn't yet been added to the window manager,
        // and this guy didn't finish itself or start another activity,
        // then go ahead and add the window.
        boolean willBeVisible = !a.mStartedActivity;
        if (!willBeVisible) {
            try {
                willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
                        a.getActivityToken());
            } catch (RemoteException e) {
            }
        }
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (a.mVisibleFromClient) {
                a.mWindowAdded = true;
                wm.addView(decor, l);
            }

        // If the window has already been added, but during resume
        // we started another activity, then don't yet make the
        // window visible.
        } else if (!willBeVisible) {
            if (localLOGV) Slog.v(
                TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }

        // Get rid of anything left hanging around.
        cleanUpPendingRemoveWindows(r);

        // The window is now visible if it has been added, we are not
        // simply finishing, and we are not starting another activity.
        if (!r.activity.mFinished && willBeVisible
                && r.activity.mDecor != null && !r.hideForNow) {
            if (r.newConfig != null) {
                r.tmpConfig.setTo(r.newConfig);
                if (r.overrideConfig != null) {
                    r.tmpConfig.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                        + r.activityInfo.name + " with newConfig " + r.tmpConfig);
                performConfigurationChanged(r.activity, r.tmpConfig);
                freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
                r.newConfig = null;
            }
            if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                    + isForward);
            WindowManager.LayoutParams l = r.window.getAttributes();
            if ((l.softInputMode
                    & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                    != forwardBit) {
                l.softInputMode = (l.softInputMode
                        & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                        | forwardBit;
                if (r.activity.mVisibleFromClient) {
                    ViewManager wm = a.getWindowManager();
                    View decor = r.window.getDecorView();
                    wm.updateViewLayout(decor, l);
                }
            }
            r.activity.mVisibleFromServer = true;
            mNumVisibleActivities++;
            if (r.activity.mVisibleFromClient) {
                r.activity.makeVisible();
            }
        }

        if (!r.onlyLocalRequest) {
            r.nextIdle = mNewActivities;
            mNewActivities = r;
            if (localLOGV) Slog.v(
                TAG, "Scheduling idle handler for " + r);
            Looper.myQueue().addIdleHandler(new Idler());
        }
        r.onlyLocalRequest = false;

        // Tell the activity manager we have resumed.
        if (reallyResume) {
            try {
                ActivityManagerNative.getDefault().activityResumed(token);
            } catch (RemoteException ex) {
            }
        }

    } else {
        // If an exception was thrown when trying to resume, then
        // just end this activity.
        try {
            ActivityManagerNative.getDefault()
                .finishActivity(token, Activity.RESULT_CANCELED, null, false);
        } catch (RemoteException ex) {
        }
    }
}
  • ActivityClientRecord r = performResumeActivity(token, clearHide);內(nèi)部會執(zhí)行到Activity的performResume最終回調(diào)到生命周期方法。
  • 通過ams設(shè)置ActivityRecord的狀態(tài)

到這里整個(gè)Activity的啟動已經(jīng)完成椅邓。我們只做了主流程的解析舍扰,而啟動的細(xì)節(jié)還是非常多了,這里也無法一一展開希坚。我們需要了解整個(gè)Activity的啟動涉及哪些類边苹,如何和ams進(jìn)行通信,以及各個(gè)類是如何協(xié)調(diào)完成這個(gè)工作裁僧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末个束,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子聊疲,更是在濱河造成了極大的恐慌茬底,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件获洲,死亡現(xiàn)場離奇詭異阱表,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)贡珊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門最爬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人门岔,你說我怎么就攤上這事爱致。” “怎么了寒随?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵糠悯,是天一觀的道長。 經(jīng)常有香客問我妻往,道長互艾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任讯泣,我火速辦了婚禮纫普,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘判帮。我一直安慰自己局嘁,他們只是感情好溉箕,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布晦墙。 她就那樣靜靜地躺著,像睡著了一般肴茄。 火紅的嫁衣襯著肌膚如雪晌畅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天寡痰,我揣著相機(jī)與錄音抗楔,去河邊找鬼棋凳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛连躏,可吹牛的內(nèi)容都是我干的剩岳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼入热,長吁一口氣:“原來是場噩夢啊……” “哼拍棕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起勺良,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤绰播,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后尚困,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蠢箩,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年事甜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谬泌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逻谦,死狀恐怖呵萨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情跨跨,我是刑警寧澤潮峦,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站勇婴,受9級特大地震影響忱嘹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜耕渴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一拘悦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧橱脸,春花似錦础米、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至栏赴,卻和暖如春蘑斧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工竖瘾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沟突,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓捕传,卻偏偏與公主長得像惠拭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子庸论,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

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