AndroidM源码学习——AMS之Activity的启动

首先上图,有一个宏观的了解,然后再细看每个函数都主要做了什么。


Activity的启动.gif

前面几个函数的逐层调用就不说了,函数的重载,从Activity的startActivityForResult方法开始

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

ActivityResult是一个内部类,它的外部类Instrumentation是安卓内部测试框架的一部分,在execStartActivity方法中会对Activity做监视与检查

     final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
    ···
      int result = ActivityManagerNative.getDefault()
                .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options, ignoreTargetSecurity, userId);
            checkStartActivityResult(result, intent);
    ···

ActivityMonitor同样是一个内部类,它用于在自动化测试中对Activity的启动作监视,checkStartActivityResult方法用来检查Activity是否异常,如在XML中未声明等问题,一些典型的检查内部如下所求:

if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_PERMISSION_USER_DENIED:
                Log.e(TAG, "User denied to start activity with intent: " + intent);
                return;
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                throw new SecurityException(
                        "Starting under voice control not allowed for: " + intent);
            case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
                // Fail silently for this case so we don't break current apps.
                // TODO(b/22929608): Instead of failing silently or throwing an exception,
                // we should properly position the activity in the stack (i.e. behind all current
                // user activity/task) and not change the positioning of stacks.
                Log.e(TAG,
                        "Not allowed to start background user activity that shouldn't be displayed"
                        + " for all users. Failing silently...");

    ...

result返回结果通过代理模式由ActivityManagerService来最终实现返回
在AMS中,startActivity调用startActivityAsUser然后调用了ActivityStackSupervisor的startActivityMayWait方法。(Task是以堆栈形式组织Activity的集合,而Task又由ActivityStack管理,ActivityStackSupervisor则是管理ActivityStack的类)

//执行权限检查
        // Collect information about the target of the Intent.
        ActivityInfo aInfo =
                resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);

        // M: To check permission for start application. @{
        if (MobileManagerUtils.isSupported()) {
            int uid = Binder.getCallingUid();
            if (!MobileManagerUtils.checkIntentPermission(intent, aInfo, mService.mContext, uid)) {
                Slog.e(TAG, "startActivity() is not granted with permission: " +
                        aInfo.permission + " from uid: " + uid);
                return ActivityManager.START_PERMISSION_USER_DENIED;
            }
        }
        // @}   
//如果APP有PRIVATE_FLAG_CANT_SAVE_STATE标记则为heavy-weight process
 if (aInfo != null &&
        (aInfo.applicationInfo.privateFlags
                &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
    // This may be a heavy-weight process!  Check to see if we already
    // have another, different heavy-weight process running.
    if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
        if (mService.mHeavyWeightProcess != null &&
                (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
                !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
            int appCallingUid = callingUid;
···
//调用startActivityLocked方法
            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);
//之后查看config是否改变
            if (stack.mConfigWillChange) {
                // If the caller also wants to switch to a new configuration,
                // do so now.  This allows a clean switch, as we are waiting
                // for the current activity to pause (so we will not destroy
                // it), and have not yet started the next activity.
                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
                        "updateConfiguration()");
                stack.mConfigWillChange = false;
                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                        "Updating to new configuration after starting activity.");
                mService.updateConfigurationLocked(config, null, false, false);
            }

在final int startActivityLocked()方法中

 ···
 //创建ProcessRecord
   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;
            }
        }
        ···
// 创建ActivityRecord
         ActivityRecord sourceRecord = null;
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            sourceRecord = 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;
                }
            }
        }
        ···
//得到ActivityRecord
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, voiceSession != null, this, container, options);
//调用startActivityUncheckedLocked()
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

在startActivityUncheckedLocked方法中判断Activity的启动方式

        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();
//查找Task,确定是否需要创建新的Task
 // We may want to try to place the new activity in to an existing task.  We always
        // do this if the target activity is singleTask or singleInstance; we will also do
        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
        // us to still place it in a new task: multi task, always doc mode, or being asked to
        // launch this as a new task behind the current one.
        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || launchSingleInstance || launchSingleTask) {
            // If bring to front is requested, and no result is requested and we have not
            // been given an explicit task to launch in to, and
            // we can find a task that was started with this same
            // component, then instead of launching bring that one to the front.
            if (inTask == null && r.resultTo == null) {
                // See if there is a task to bring to the front.  If this is
                // a SINGLE_INSTANCE activity, there can be one and only one
                // instance of it in the history, and it is always in its own
                // unique task, so we do a special search.
                ActivityRecord intentActivity = !launchSingleInstance ?
                        findTaskLocked(r) : findActivityLocked(intent, r.info);
                if (intentActivity != 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 (isLockTaskModeViolation(intentActivity.task,
                            (launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
                        showLockTaskToast();
                        Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
                        return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
                    }
                    if (r.task == null) {
                        r.task = intentActivity.task;
                    }
    //以下几种情况要创建新的栈
 if (inTask == null) {
            if (sourceRecord == null) {
                // This activity is not being started from another...  in this
                // case we -always- start a new task.
                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
                }
            } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                // The original activity who is starting us is running as a single
                // instance...  this new activity it is starting must go on its
                // own task.
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
            } else if (launchSingleInstance || launchSingleTask) {
                // The activity being started is a single instance...  it always
                // gets launched into its own task.
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
            }
        }
    
    //如不为空且目标不是栈顶,则将目标移动到栈顶
    // If the target task is not in the front, then we need
    // to bring it to the front...  except...  well, with
    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
    // to have the same behavior as if a new instance was
    // being started, which means not bringing it to the front
    // if the caller is not itself in the front.
    final ActivityStack focusStack = getFocusedStack();
    ActivityRecord curTop = (focusStack == null)
            ? null : focusStack.topRunningNonDelayedActivityLocked(notTop);
    boolean movedToFront = false;
    if (curTop != null && (curTop.task != intentActivity.task ||
            curTop.task != focusStack.topTask())) {
        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
        if (sourceRecord == null || (sourceStack.topActivity() != null &&
                sourceStack.topActivity().task == sourceRecord.task)) {
            // We really do want to push this one into the user's face, right now.
            if (launchTaskBehind && sourceRecord != null) {
                intentActivity.setTaskToAffiliateWith(sourceRecord.task);
            }
            movedHome = true;
            targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation,
                    options, r.appTimeTracker, "bringingFoundTaskToFront");
            movedToFront = true;
            if ((launchFlags &
                    (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
                // Caller wants to appear on home activity.
                intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
            }
            options = null;

            /// M: Fix ALPS01276300, at this case, avoid move home to top when resume top @{
            intentActivity.task.mMovingToFront = true;
            Slog.d(TAG_TASKS, "Set intentActivity.task.mMovingToFront = true");
            /// @}
        }
    }
    if (!movedToFront) {
        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + targetStack
                + " from " + intentActivity);
        targetStack.moveToFront("intentActivityFound");
    }
    
    //如果栈顶即为目标Activity直接resumeTopActivitiesLocked();
  if (r.packageName != null) {
            // If the activity being launched is the same as the one currently
            // at the top, then we need to check if it should only be launched
            // once.
            ActivityStack topStack = mFocusedStack;
            ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
            if (top != null && r.resultTo == null) {
                if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                    if (top.app != null && top.app.thread != null) {
                        if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                            || launchSingleTop || launchSingleTask) {
                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
                                    top.task);
                            /// M: AMS log enhancement @{
                            if (!ActivityManagerService.IS_USER_BUILD)
                               Slog.d(TAG, "ACT-AM_NEW_INTENT " + top + top.task);
                            /// @}
                            // For paranoia, make sure we have correctly
                            // resumed the top activity.
                            topStack.mLastPausedActivity = null;
                            if (doResume) {
                                resumeTopActivitiesLocked();
                            }
                            ActivityOptions.abort(options);
                            if ((startFlags&ActivityManager.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 ActivityManager.START_RETURN_INTENT_TO_CALLER;
                            }
                            top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
                            return ActivityManager.START_DELIVERED_TO_TOP;
                        }
                    }
                }
            }

        } 
//创建一个新的Task并置于栈顶
    ActivityRecord prev = targetStack.topActivity();
    r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(),
                    r.info, intent, null, null, true), null);
    mWindowManager.moveTaskToTop(r.task.taskId);
    if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
            + " in new guessed " + r.task);
//最后由AMS给权限并启动
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
                intent, r.getUriPermissionsLocked(), r.userId);
···
ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
/// M: AMS log enhancement @{
if (!ActivityManagerService.IS_USER_BUILD)
   Slog.d(TAG, "ACT-AM_CREATE_ACTIVITY " + r + r.task);
/// @}

targetStack.mLastPausedActivity = null;
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");
}

在ActivityStack的startActivityLocked方法中加入窗口管理WindowManager

if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
                mNoAnimActivities.add(r);
            } else {
                mWindowManager.prepareAppTransition(newTask
                        ? r.mLaunchTaskBehind
                                ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
                                : AppTransition.TRANSIT_TASK_OPEN
                        : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
                mNoAnimActivities.remove(r);
            }
            mWindowManager.addAppToken(task.mActivities.indexOf(r),
                    r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                    (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
                    r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);

如果可见堆栈的顶部与焦点堆栈相同则调用ActivityStackSupervisor的resumeTopActivitiesLocked方法,而在该方法中调用resumeTopActivityInnerLocked方法移动焦点

//将焦点移到下一个可见的正在运行的activity
 final String reason = "noMoreActivities";
if (!mFullscreen) {
    // Try to move focus to the next visible stack with a running activity if this
    // stack is not covering the entire screen.
    final ActivityStack stack = getNextVisibleStackLocked();
    if (adjustFocusToNextVisibleStackLocked(stack, reason)) {
        return mStackSupervisor.resumeTopActivitiesLocked(stack, prev, null);
    }
}
// Let's just start up the Launcher...
ActivityOptions.abort(options);                 
//如果需要则中断当前的Activity
// We need to start pausing the current activity so the top one
// can be resumed...
boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
if (mResumedActivity != null) {
    if (DEBUG_STATES) Slog.d(TAG_STATES,
            "resumeTopActivityLocked: Pausing " + mResumedActivity);
    pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
//将暂停的Activity置为不可见,新的Activity置为可见,之后通知wm
 if (prev != null && prev != next) {
    if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev)
            && next != null && !next.nowVisible) {
        mStackSupervisor.mWaitingVisibleActivities.add(prev);
        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                "Resuming top, waiting visible to hide: " + prev);
    } else {
        // The next activity is already visible, so hide the previous
        // activity's windows right now so we can show the new one ASAP.
        // We only do this if the previous is finishing, which should mean
        // it is on top of the one being resumed so hiding it quickly
        // is good.  Otherwise, we want to do the normal route of allowing
        // the resumed activity to be shown so we can decide if the
        // previous should actually be hidden depending on whether the
        // new one is found to be full-screen or not.
        if (prev.finishing) {
            mWindowManager.setAppVisibility(prev.appToken, false);
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                    "Not waiting for visible to hide: " + prev + ", waitingVisible="
                    + mStackSupervisor.mWaitingVisibleActivities.contains(prev)
                    + ", nowVisible=" + next.nowVisible);
        } else {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                    "Previous already visible but still waiting to hide: " + prev
                    + ", waitingVisible="
                    + mStackSupervisor.mWaitingVisibleActivities.contains(prev)
                    + ", nowVisible=" + next.nowVisible);
        }
    }
}
···
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);
    }
}       
//如果Activity所在进程存在,先恢复其状态
next.sleeping = false;
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(mService.mTopProcessState);
next.clearOptionsLocked();
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
        mService.isNextTransitionForward(), resumeAnimOptions);
mStackSupervisor.checkReadyForSleepLocked();

然后调用ActivityStackSupervisor的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);
            }
            //如果不是第一次启动直接startActivity
            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);
}

ActivityManagerService的startProcessLocked方法创建新的进程

 Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);

那么新创建的这个进程如何与要启动的Activity关联在一起呢,我们知道,Activity的真正入口是ActivityThread的main方法,核心操作如下

Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);

在此attach方法中做进程与应用的绑定

RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
    mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
    // Ignore
}

通过代理它的真正实现位于AMS的attachApplicationLocked

thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
        profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
        app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
        isRestrictedBackupMode || !normalMode, app.persistent,
        new Configuration(mConfiguration), app.compat,
        getCommonServicesLocked(app.isolated),
        mCoreSettingsObserver.getCoreSettingsLocked());
//之后交给ASS启动
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
    try {
        if (mStackSupervisor.attachApplicationLocked(app)) {
            didSomething = true;
        }
    } catch (Exception e) {
        Slog.e(TAG, "Exception thrown launching activities in " + app, e);
        Slog.e(TAG, Log.getStackTraceString(new Throwable()));
        badApp = true;
    }
}

回到ActivityStackSupervisor,调用attachApplicationLocked方法,查询栈顶Activity然后启动

ActivityRecord hr = stack.topRunningActivityLocked(null);
if (hr != null) {
    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
            && processName.equals(hr.processName)) {
        try {
            if (realStartActivityLocked(hr, app, true, true)) {
                didSomething = true;
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception in new application when starting activity "
                  + hr.intent.getComponent().flattenToShortString(), e);
            throw e;
        }
    }
}

在realStartActivityLocked方法中会对Configuration的状态是否改变进行检查

if (checkConfig) {
    Configuration config = mWindowManager.updateOrientationFromAppTokens(
            mService.mConfiguration,
            r.mayFreezeScreenLocked(app) ? r.appToken : null);
    mService.updateConfigurationLocked(config, r, false, false);
}

通知Activity所在进程进行启动

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

在ActivityThread的scheduleLaunchActivity方法中使用Message发送消息

ActivityClientRecord r = new ActivityClientRecord();

r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;

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

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

r.profilerInfo = profilerInfo;

r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);

sendMessage(H.LAUNCH_ACTIVITY, r);

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    Message msg = Message.obtain();
    msg.what = what;
    msg.obj = obj;
    msg.arg1 = arg1;
    msg.arg2 = arg2;
    if (async) {
        msg.setAsynchronous(true);
    }
    mH.sendMessage(msg);
}

Thread收到消息后调用handlerLaunchActivity方法得到启动的Activity

 Activity a = performLaunchActivity(r, customIntent);
 //performLaunchActivity方法使用类的加载器加载得到相应的activity
 Activity activity = null;
try {
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);
    StrictMode.incrementExpectedActivityCount(activity.getClass());
    r.intent.setExtrasClassLoader(cl);
    r.intent.prepareToEnterProcess();
    if (r.state != null) {
        r.state.setClassLoader(cl);
    }
} catch (Exception e) {
    if (!mInstrumentation.onException(activity, e)) {
        throw new RuntimeException(
            "Unable to instantiate activity " + component
            + ": " + e.toString(), e);
    }
}

在performLaunchActivity方法中获取Activity的配置信息(Configuration、Theme等),然后调用Activity生命周期的方法

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

补充一下当前Activity被pause的几个方法:
ActivityStack的startPausingLocke方法
通过Proxy调用ApplicationThread的schedulePauseActivity方法

prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
        userLeaving, prev.configChangeFlags, dontWait);

在activity开始启动的过程中保持设备处于唤醒状态,并停止按键的分发

// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
if (!uiSleeping && !mService.isSleepingOrShuttingDown()) {
    mStackSupervisor.acquireLaunchWakelock();
}
...
 // Have the window manager pause its key dispatching until the new
// activity has started.  If we're pausing the activity just because
// the screen is being turned off and the UI is sleeping, don't interrupt
// key dispatch; the same activity will pick it up again on wakeup.
if (!uiSleeping) {
    prev.pauseKeyDispatchingLocked();
} 

在schedulePauseActivity方法中通过Message发送消息,同理handlerMessage中调用handlePauseActivity,然后调用AMS的activityPaused方法

try {
        ActivityManagerNative.getDefault().activityPaused(token);
    } catch (RemoteException ex) {
}

ActivityManagerService的activityPaused方法

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

调用ActivityStack的activityPausedLocked方法,在activityPausedLocked中再调用completePauseLocked方法,之后回到ActivityStackSupervisor的resumeTopActivitiesLocked方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容