美文网首页Android 源码分析
AndroidM源码学习——AMS之Activity的启动

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

作者: 奥利奥真好吃 | 来源:发表于2018-01-30 15:26 被阅读141次

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


    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方法

    相关文章

      网友评论

        本文标题:AndroidM源码学习——AMS之Activity的启动

        本文链接:https://www.haomeiwen.com/subject/aecczxtx.html