android Activity启动流程(2)

/ android / 1 条评论 / 1062浏览

用到的代码文件

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java
frameworks/base/core/java/com/android/internal/app/ActivityTrigger.java
frameworks/base/core/java/android/app/ApplicationThreadNative.java中定义ApplicationThreadProxy类

代称执行流程

android activity start 查看原图

模块编译

mm frameworks/base/services/ -> system/framework/services.jar
mm frameworks/base/ -> system/framework/framework.jar

android activity启动流程

本文接着 android Activity启动流程(1) 这篇文章继续分析。
下面的代码是以android N(api 24)为基础来进行。

通过前文描述的进程间通信,最终由ActivityManagerService接收到消息,进而调用startActivity()方法。

@Override
public final int startActivity(IApplicationThread caller, 
        String callingPackage,Intent intent, String resolvedType, 
        IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) 
{
    /*
    caller: android.app.ApplicationThreadProxy@753eae5
    callingPackage: com.tct.launcher
      
    intent: Intent { act=android.intent.action.MAIN 
    cat=[android.intent.category.LAUNCHER] 
    flg=0x10200000 
    cmp=com.jrdcom.filemanager/.activity
        .FileBrowserActivity (has extras) }
          
    resolvedType: null
    
    resultTo: 
        Token{74e99b4 ActivityRecord{a68687 u0 
            com.tct.launcher/.Launcher t6}}
        
    resultWho: null
    requestCode: -1
    startFlags: 0
    profilerInfo: null
    bOptions: Bundle[mParcelledData.dataSize=636]
    */
    return startActivityAsUser(caller, callingPackage, intent, 
            resolvedType, resultTo,resultWho, requestCode, 
            startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

可以看见在startActivity()方法中实际调用的是startActivityAsUser()方法。

final ActivityStarter mActivityStarter;

@Override
public final int startActivityAsUser(IApplicationThread caller, 
        String callingPackage,Intent intent, String resolvedType, 
        IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, 
        int userId) {
    enforceNotIsolatedCaller("startActivity");
   /*
    userId: 0;
    Binder.getCallingPid(): 3171
    Binder.getCallingUid(): 10112
    */
    userId = mUserController
      .handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
            userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, 
            callingPackage, intent,resolvedType, null, null, 
            resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, bOptions, false, userId, 
            null, null);
}

可以看见进入ActivityStarter类中,并调用其startActivityMayWait()方法。 . 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, IActivityManager.WaitResult outResult, 
        Configuration config,Bundle bOptions, 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");
    }
    mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
    boolean componentSpecified = intent.getComponent() != null;

    // Save a copy in case ephemeral needs it
    final Intent ephemeralIntent = new Intent(intent);
    // Don't modify the client's object!
    intent = new Intent(intent);

    ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
    if (rInfo == null) {
        UserInfo userInfo = mSupervisor.getUserInfo(userId);
        if (userInfo != null && userInfo.isManagedProfile()) {
            // Special case for managed profiles, if attempting to launch 
            // non-cryto aware app in a locked managed profile from an 
            // unlocked parent allow it to resolve as user will be sent 
            // via confirm credentials to unlock the profile.
            UserManager userManager = UserManager.get(mService.mContext);
            boolean profileLockedAndParentUnlockingOrUnlocked = false;
            long token = Binder.clearCallingIdentity();
            try {
                UserInfo parent = userManager.getProfileParent(userId);
                profileLockedAndParentUnlockingOrUnlocked = (parent != null)
                        && userManager.isUserUnlockingOrUnlocked(parent.id)
                        && !userManager.isUserUnlockingOrUnlocked(userId);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
            if (profileLockedAndParentUnlockingOrUnlocked) {
                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                        PackageManager.MATCH_DIRECT_BOOT_AWARE
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
            }
        }
    }
    // Collect information about the target of the Intent.
    ActivityInfo aInfo = mSupervisor
            .resolveActivity(intent, rInfo, startFlags, profilerInfo);

    ActivityOptions options = ActivityOptions.fromBundle(bOptions);
    ActivityStackSupervisor.ActivityContainer container =
            (ActivityStackSupervisor.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 = mSupervisor.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();

        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)) {
                final ProcessRecord heavy = mService.mHeavyWeightProcess;
                if (heavy != null 
                        && (heavy.info.uid != aInfo.applicationInfo.uid
                        || !heavy.processName.equals(aInfo.processName))) {
                    int appCallingUid = callingUid;
                    if (caller != null) {
                        ProcessRecord callerApp = mService
                            .getRecordForAppLocked(caller);
                        if (callerApp != null) {
                            appCallingUid = callerApp.info.uid;
                        } else {
                            Slog.w(TAG, "Unable to find app for caller " 
                                  + caller
                                    + " (pid=" + callingPid + ") when starting: "
                                    + intent.toString());
                            ActivityOptions.abort(options);
                            return ActivityManager.START_PERMISSION_DENIED;
                        }
                    }

                    IIntentSender target = mService.getIntentSenderLocked(
                            ActivityManager.INTENT_SENDER_ACTIVITY, 
                            "android",
                            appCallingUid, userId, null, null, 0, 
                            new Intent[] { intent },
                            new String[] { resolvedType }, 
                                    PendingIntent.FLAG_CANCEL_CURRENT
                                    | PendingIntent.FLAG_ONE_SHOT, null);

                    Intent newIntent = new Intent();
                    if (requestCode >= 0) {
                        // Caller is requesting a result.
                        newIntent.putExtra(HeavyWeightSwitcherActivity
                            .KEY_HAS_RESULT, true);
                    }
                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
                            new IntentSender(target));
                    if (heavy.activities.size() > 0) {
                        ActivityRecord hist = heavy.activities.get(0);
                        newIntent.putExtra(
                                HeavyWeightSwitcherActivity.KEY_CUR_APP,
                                hist.packageName);
                        newIntent.putExtra(
                                HeavyWeightSwitcherActivity.KEY_CUR_TASK,
                                hist.task.taskId);
                    }
                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
                            aInfo.packageName);
                    newIntent.setFlags(intent.getFlags());
                    newIntent.setClassName("android",
                            HeavyWeightSwitcherActivity.class.getName());
                    intent = newIntent;
                    resolvedType = null;
                    caller = null;
                    callingUid = Binder.getCallingUid();
                    callingPid = Binder.getCallingPid();
                    componentSpecified = true;
                    rInfo = mSupervisor.resolveIntent(intent, 
                          null /*resolvedType*/, userId);
                    aInfo = rInfo != null ? rInfo.activityInfo : null;
                    if (aInfo != null) {
                        aInfo = mService.getActivityInfoForUser(aInfo, userId);
                    }
                }
            }
        }

        final ActivityRecord[] outRecord = new ActivityRecord[1];
         /**
          * 进入这里
          * 又调用ActivityStarter.startActivityLocked()方法
          */
        int res = startActivityLocked(caller, intent, ephemeralIntent, 
                resolvedType,aInfo, rInfo, voiceSession, voiceInteractor,
                resultTo, resultWho, requestCode, callingPid,callingUid, 
                callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, 
                outRecord, container, inTask);

        Binder.restoreCallingIdentity(origId);

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

        if (outResult != null) {
            outResult.result = res;
            if (res == ActivityManager.START_SUCCESS) {
                mSupervisor.mWaitingActivityLaunched.add(outResult);
                do {
                    try {
                        mService.wait();
                    } catch (InterruptedException e) {
                    }
                } while (outResult.result != START_TASK_TO_FRONT
                        && !outResult.timeout && outResult.who == null);
                if (outResult.result == START_TASK_TO_FRONT) {
                    res = START_TASK_TO_FRONT;
                }
            }
            if (res == START_TASK_TO_FRONT) {
                ActivityRecord r = stack.topRunningActivityLocked();
                if (r.nowVisible && r.state == RESUMED) {
                    outResult.timeout = false;
                    outResult.who = new ComponentName(r.info.packageName, 
                        r.info.name);
                    outResult.totalTime = 0;
                    outResult.thisTime = 0;
                } else {
                    outResult.thisTime = SystemClock.uptimeMillis();
                    mSupervisor.mWaitingActivityVisible.add(outResult);
                    do {
                        try {
                            mService.wait();
                        } catch (InterruptedException e) {
                        }
                    } while (!outResult.timeout && outResult.who == null);
                }
            }
        }

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

//State and management of a single stack of activities. management:管理部门
ActivityStack.java

//An entry in the history stack, representing an activity.
ActivityRecord.java

接下来调用ActivityStarter类中的startActivityLocked()方法。

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

    ProcessRecord callerApp = null;
    if (caller != null) {
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) {
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        } else {
            Slog.w(TAG, "Unable to find app for caller " + caller
                    + " (pid=" + callingPid + ") when starting: "
                    + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }

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

    ActivityRecord sourceRecord = null;
    ActivityRecord resultRecord = null;
    if (resultTo != null) {
        sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                "Will send result to " + resultTo + " " + sourceRecord);
        if (sourceRecord != null) {
            if (requestCode >= 0 && !sourceRecord.finishing) {
                resultRecord = sourceRecord;
            }
        }
    }

    final int launchFlags = intent.getFlags();

    if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 
        && sourceRecord != null) {
        // Transfer the result target from the source activity to the new
        // one being started, including any failures.
        if (requestCode >= 0) {
            ActivityOptions.abort(options);
            return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
        }
        resultRecord = sourceRecord.resultTo;
        if (resultRecord != null && !resultRecord.isInStackLocked()) {
            resultRecord = null;
        }
        resultWho = sourceRecord.resultWho;
        requestCode = sourceRecord.requestCode;
        sourceRecord.resultTo = null;
        if (resultRecord != null) {
            resultRecord.removeResultsLocked(sourceRecord, 
                resultWho, requestCode);
        }
        if (sourceRecord.launchedFromUid == callingUid) {
            // The new activity is being launched from the same uid as the 
            // previous activity in the flow, and asking to forward its result 
            // back to the previous.  In this case the activity is serving as 
            // a trampoline between the two, so we also want to update
            // its launchedFromPackage to be the same as the previous 
            // activity.  Note that this is safe, since we know these two 
            // packages come from the same uid; the caller could just as
            // well have supplied that same package name itself.  This 
            // specifially deals with the case of an intent picker/chooser
            // being launched in the app
            // flow to redirect to an activity picked by the user, where
            // we want the final activity to consider it to have been
            // launched by the previous app activity.
            callingPackage = sourceRecord.launchedFromPackage;
        }
    }

    if (err == ActivityManager.START_SUCCESS 
        && intent.getComponent() == null) {
        // We couldn't find a class that can handle the given Intent.
        // That's the end of that!
        err = ActivityManager.START_INTENT_NOT_RESOLVED;
    }

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

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

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

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

    if (err != START_SUCCESS) {
        if (resultRecord != null) {
            resultStack.sendActivityResultLocked(
                    -1, resultRecord, resultWho, requestCode, 
                    RESULT_CANCELED, null);
        }
        ActivityOptions.abort(options);
        return err;
    }

    boolean abort = !mSupervisor.checkStartAnyActivityPermission(
            intent, aInfo, resultWho,requestCode, callingPid, callingUid, 
            callingPackage, ignoreTargetSecurity, callerApp,
            resultRecord, resultStack, options);
    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
            callingPid, resolvedType, aInfo.applicationInfo);

    if (mService.mController != null) {
        try {
            // The Intent we give to the watcher has the extra data
            // stripped off, since it can contain private information.
            Intent watchIntent = intent.cloneFilter();
            abort |= !mService.mController.activityStarting(watchIntent,
                    aInfo.applicationInfo.packageName);
        } catch (RemoteException e) {
            mService.mController = null;
        }
    }

    mInterceptor.setStates(userId, realCallingPid, realCallingUid, 
          startFlags, callingPackage);
    mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, 
          callingPid, callingUid,options);
    intent = mInterceptor.mIntent;
    rInfo = mInterceptor.mRInfo;
    aInfo = mInterceptor.mAInfo;
    resolvedType = mInterceptor.mResolvedType;
    inTask = mInterceptor.mInTask;
    callingPid = mInterceptor.mCallingPid;
    callingUid = mInterceptor.mCallingUid;
    options = mInterceptor.mActivityOptions;
    if (abort) {
        if (resultRecord != null) {
            resultStack.sendActivityResultLocked(-1, resultRecord, 
                    resultWho, requestCode,
                    RESULT_CANCELED, null);
        }
        // We pretend to the caller that it was really started, but
        // they will just get a cancel result.
        ActivityOptions.abort(options);
        return START_SUCCESS;
    }

    // If permissions need a review before any of the app 
    // components can run, we launch the review activity 
    // and pass a pending intent to start the activity
    // we are to launching now after the review is completed.
    if (Build.PERMISSIONS_REVIEW_REQUIRED 
          && aInfo != null) {
        if (mService.getPackageManagerInternalLocked()
                .isPermissionsReviewRequired(
                aInfo.packageName, userId)) {
            IIntentSender target = mService.getIntentSenderLocked(
                    ActivityManager.INTENT_SENDER_ACTIVITY, 
                    callingPackage,callingUid, userId, null, null, 0, 
                    new Intent[]{intent},new String[]{resolvedType}, 
                    PendingIntent.FLAG_CANCEL_CURRENT
                            | PendingIntent.FLAG_ONE_SHOT, null);

            final int flags = intent.getFlags();
            Intent newIntent = new Intent(
                Intent.ACTION_REVIEW_PERMISSIONS);
            newIntent.setFlags(flags
                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, 
                    aInfo.packageName);
            newIntent.putExtra(Intent.EXTRA_INTENT, 
                    new IntentSender(target));
            if (resultRecord != null) {
                newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, 
                      true);
            }
            intent = newIntent;

            resolvedType = null;
            callingUid = realCallingUid;
            callingPid = realCallingPid;

            rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
                    null /*profilerInfo*/);
            ......
        }
    }

    // If we have an ephemeral app, abort the process of launching the
    // resolved intent.Instead, launch the ephemeral installer.
    // Once the installer is finished, it starts either the intent
    // we resolved here [on install error] or the ephemeral
    // app [on install success].
    if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
        // Create a pending intent to start the intent resolved here.
        final IIntentSender failureTarget = 
            mService.getIntentSenderLocked(
                ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
                Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
                new String[]{ resolvedType },
                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
                        | PendingIntent.FLAG_IMMUTABLE, null);

        // Create a pending intent to start the ephemeral application; 
        // force it to be directed to the ephemeral package.
        ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo
                  .getPackageName());
        final IIntentSender ephemeralTarget = 
              mService.getIntentSenderLocked(
                ActivityManager.INTENT_SENDER_ACTIVITY, 
                callingPackage,Binder.getCallingUid(), userId, null, 
                null, 0, new Intent[]{ ephemeralIntent },
                new String[]{ resolvedType },
                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
                        | PendingIntent.FLAG_IMMUTABLE, null);

        int flags = intent.getFlags();
        intent = new Intent();
        intent.setFlags(flags
                | Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
                rInfo.ephemeralResolveInfo.getPackageName());
        intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, 
                new IntentSender(failureTarget));
        intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, 
                new IntentSender(ephemeralTarget));

        resolvedType = null;
        callingUid = realCallingUid;
        callingPid = realCallingPid;

        rInfo = rInfo.ephemeralInstaller;
        aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, 
                null /*profilerInfo*/);
    }

    //创建一个ActivityRecord for current start intent
    ActivityRecord r = new ActivityRecord(mService, callerApp,
            callingUid, callingPackage, intent, resolvedType, aInfo, 
            mService.mConfiguration, resultRecord, resultWho,
            requestCode, componentSpecified, voiceSession != null, 
            mSupervisor, container,
            options, sourceRecord);
    if (outActivity != null) {
        outActivity[0] = r;
    }

    if (r.appTimeTracker == null && sourceRecord != null) {
        // If the caller didn't specify an explicit time tracker, 
        // we want to continue
        // tracking under any it has.
        r.appTimeTracker = sourceRecord.appTimeTracker;
    }

    final ActivityStack stack = mSupervisor.mFocusedStack;
    if (voiceSession == null && (stack.mResumedActivity == null
            || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                realCallingPid, realCallingUid, "Activity start")) {
            PendingActivityLaunch pal =  new PendingActivityLaunch(r,
                    sourceRecord, startFlags, stack, callerApp);
            mPendingActivityLaunches.add(pal);
            ActivityOptions.abort(options);
            return ActivityManager.START_SWITCHES_CANCELED;
        }
    }

    if (mService.mDidAppSwitch) {
        // This is the second allowed switch since we stopped switches,
        // so now just generally allow switches.  Use case: user presses
        // home (switches disabled, switch to home, mDidAppSwitch now true);
        // user taps a home icon (coming from home so allowed, we hit here
        // and now allow anyone to switch again).
        mService.mAppSwitchesAllowedTime = 0;
    } else {
        mService.mDidAppSwitch = true;
    }

    doPendingActivityLaunchesLocked(false);

    try {
        //推迟surface layout, 当调用这个方法以后,直到有一个用户调
        // 用了continueSurfaceLayout才恢复layout
        mService.mWindowManager.deferSurfaceLayout();
        /*
         * 进入这里
         */
        err = startActivityUnchecked(r, sourceRecord, voiceSession, 
                voiceInteractor, startFlags,
                true, options, inTask);
    } finally {
        mService.mWindowManager.continueSurfaceLayout();
    }
    postStartActivityUncheckedProcessing(r, err, stack.mStackId, 
        mSourceRecord, mTargetStack);
    return err;
}

接下来调用ActivityStarter类中startActivityUnchecked()方法。

private int startActivityUnchecked(final ActivityRecord r, 
        ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, 
        IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, 
        TaskRecord inTask) {
    Log.i(MTAG,"method called startActivityUnchecked()");
    setInitialState(r, options, inTask, doResume, startFlags, 
        sourceRecord, voiceSession,voiceInteractor);

    computeLaunchingTaskFlags();

    computeSourceStack();

    mIntent.setFlags(mLaunchFlags);

    mReusedActivity = getReusableIntentActivity();
    Log.i(MTAG,"mReusedActivity: "+mReusedActivity);
    final int preferredLaunchStackId =
            (mOptions != null) ? 
            mOptions.getLaunchStackId() : INVALID_STACK_ID;

    if (mReusedActivity != null) {
        // When the flags NEW_TASK and CLEAR_TASK are set, 
        // then the task gets reused but still needs to be a lock task 
        // mode violation since the task gets cleared out and
        // the device would otherwise leave the locked task.
        if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
                (mLaunchFlags 
                & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
            mSupervisor.showLockTaskToast();
            Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

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

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

        mReusedActivity = 
            setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);

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

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

    Log.i(MTAG,"mStartActivity.packageName: "
        +mStartActivity.packageName);
    if (mStartActivity.packageName == null) {
        if (mStartActivity.resultTo != null 
              && mStartActivity.resultTo.task.stack != null) {
            mStartActivity.resultTo.task.stack.sendActivityResultLocked(
                    -1, mStartActivity.resultTo, mStartActivity.resultWho,
                    mStartActivity.requestCode, RESULT_CANCELED, null);
        }
        ActivityOptions.abort(mOptions);
        return START_CLASS_NOT_FOUND;
    }

    // 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.
    final ActivityStack topStack = mSupervisor.mFocusedStack;
    final ActivityRecord top = topStack
            .topRunningNonDelayedActivityLocked(mNotTop);
    final boolean dontStart = top != null && mStartActivity.resultTo == null
            && top.realActivity.equals(mStartActivity.realActivity)
            && top.userId == mStartActivity.userId
            && top.app != null && top.app.thread != null
            && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
            || mLaunchSingleTop || mLaunchSingleTask);
    Log.i(MTAG,"dontStart: "+dontStart);
    Log.i(MTAG,"mDoResume: "+mDoResume);
    if (dontStart) {
        ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
        // For paranoia, make sure we have correctly resumed 
        // the top activity.
        topStack.mLastPausedActivity = null;
        if (mDoResume) {
            mSupervisor.resumeFocusedStackTopActivityLocked();
        }
        ActivityOptions.abort(mOptions);
        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client
            //  said not to do
            // anything if that is the case, so this is it!
            return START_RETURN_INTENT_TO_CALLER;
        }
        top.deliverNewIntentLocked(
                mCallingUid, mStartActivity.intent, 
                mStartActivity.launchedFromPackage);

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

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

    // Should this be considered a new task?
    if (mStartActivity.resultTo == null && mInTask == null 
            && !mAddingToTask
            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        setTaskFromReuseOrCreateNewTask(taskToAffiliate);

        if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" 
                  + mStartActivity);
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }
        if (!mMovedOtherTask) {
            updateTaskReturnToType(mStartActivity.task, mLaunchFlags, 
                  topStack);
        }
    } else if (mSourceRecord != null) {
        if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" 
                  + mStartActivity);
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

        final int result = setTaskFromSourceRecord();
        if (result != START_SUCCESS) {
            return result;
        }
    } else if (mInTask != null) {
        // The caller is asking that the new activity be started in an explicit
        // task it has provided to us.
        if (mSupervisor.isLockTaskModeViolation(mInTask)) {
            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" 
                  + mStartActivity);
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

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

    mService.grantUriPermissionFromIntentLocked(mCallingUid,
             mStartActivity.packageName,
            mIntent, mStartActivity.getUriPermissionsLocked(), 
            mStartActivity.userId);

    if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
        mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
    }
    if (newTask) {
        EventLog.writeEvent(
                EventLogTags.AM_CREATE_TASK, mStartActivity.userId, 
                mStartActivity.task.taskId);
    }
    ActivityStack.logStartActivity(
            EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, 
            mStartActivity.task);
    mTargetStack.mLastPausedActivity = null;
    mTargetStack.startActivityLocked(mStartActivity, newTask, 
          mKeepCurTransition, mOptions);
    Log.i(MTAG,"mDoResume: "+mDoResume);
    Log.i(MTAG,"mLaunchTaskBehind: "+mLaunchTaskBehind);
    if (mDoResume) {
        if (!mLaunchTaskBehind) {
            // TODO(b/26381750): Remove this code after verification 
            // that all the decision points above moved targetStack to 
            // the front which will also set the focus activity.
            mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
        }
        final ActivityRecord topTaskActivity = 
              mStartActivity.task.topRunningActivityLocked();
        Log.i(MTAG,"topTaskActivity: "+topTaskActivity);
        if (!mTargetStack.isFocusable()
                || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                && mStartActivity != topTaskActivity)) {
            Log.i(MTAG,"if judge : true");
            // If the activity is not focusable, we can't resume it, 
            // but still would like to
            // make sure it becomes visible as it starts (this will 
            // also trigger entry animation). An example of this are 
            //PIP activities.
            // Also, we don't want to resume activities in a task 
            // that currently has an overlay
            // as the starting activity just needs to be in the 
            // visible paused state until the
            // over is removed.
            mTargetStack.ensureActivitiesVisibleLocked(null,
                  0, !PRESERVE_WINDOWS);
            // Go ahead and tell window manager to execute app 
            // transition for this activity  since the app transition 
            // will not be triggered through the resume channel.
            mWindowManager.executeAppTransition();
        } else {
            /**
             * 打印log进入到了这里
             */
            mSupervisor.resumeFocusedStackTopActivityLocked(
                    mTargetStack, mStartActivity,mOptions);
        }
    } else {
        mTargetStack.addRecentActivityLocked(mStartActivity);
    }
    mSupervisor.updateUserStackLocked(mStartActivity.userId, 
          mTargetStack);

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

    return START_SUCCESS;
}

接下来调用的是ActivityStackSupervisor类中resumeFocusedStackTopActivityLocked()方法。

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, 
        ActivityOptions targetOptions) {
    /*
    targetStack: ActivityStack{c80291b stackId=1, 1 tasks}
    
    target: ActivityRecord{5b2371e u0 
    com.jrdcom.filemanager/.activity.FileBrowserActivity t18}
    
    targetOptions: ActivityOptions(249317539), mPackageName=null, 
    mAnimationType=11, mStartX=360, mStartY=633, 
    mWidth=81, mHeight=81 
    */
    /**
      * 我这里是launcher启动一个应用 ,所以当前launcher所处的
      * stack不为null,
      * 并且stack的父容器的父activity所处的stack与当前stack相等
      * 所以进入这个逻辑
      */
    if (targetStack != null && isFocusedStack(targetStack)) {
        Log.i(MTAG,"stack --> if judge true");
        return targetStack.resumeTopActivityUncheckedLocked(target, 
              targetOptions);
    }
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    if (r == null || r.state != RESUMED) {
        Log.i(MTAG,"r --> if judge true");
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    }
    return false;
}

接下来调用的是ActivityStack类中resumeTopActivityUncheckedLocked()方法。

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, 
    ActivityOptions 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;
}

接下来调用的是ActivityStack类中resumeTopActivityInnerLocked()方法。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, 
    ActivityOptions options) {
    if (DEBUG_LOCKSCREEN) mService.logLockScreen("");

    if (!mService.mBooting && !mService.mBooted) {
        // Not ready yet!
        return false;
    }

    ActivityRecord parent = mActivityContainer.mParentActivity;
    if ((parent != null && parent.state != ActivityState.RESUMED) ||
            !mActivityContainer.isAttachedLocked()) {
        // Do not resume this stack if its parent is not resumed.
        // TODO: If in a loop, make sure that parent stack 
        // resumeTopActivity is called 1st.
        return false;
    }

    mStackSupervisor.cancelInitializingActivities();

    // Find the first activity that is not finishing.
    final ActivityRecord next = topRunningActivityLocked();
    log("next: "+next);

    // Remember how we'll process this pause/resume situation, 
    // and ensure that the state is reset however we wind up proceeding.
    final boolean userLeaving = mStackSupervisor.mUserLeaving;
    log("userLeaving: "+userLeaving);
    mStackSupervisor.mUserLeaving = false;

    final TaskRecord prevTask = prev != null ? prev.task : null;
    if (next == null) {
        // There are no more activities!
        final String reason = "noMoreActivities";
        final int returnTaskType = 
                prevTask == null || !prevTask.isOverHomeStack()
                ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
        if (!mFullscreen 
            && adjustFocusToNextFocusableStackLocked(
                  returnTaskType, reason)) {
            // Try to move focus to the next visible stack with a r
            // unning activity if this
            // stack is not covering the entire screen.
            return mStackSupervisor.resumeFocusedStackTopActivityLocked(
                    mStackSupervisor.getFocusedStack(), prev, null);
        }

        // Let's just start up the Launcher...
        ActivityOptions.abort(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: No more activities go home");
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        // Only resume home if on home display
        return isOnHomeDisplay() &&
                mStackSupervisor.resumeHomeStackTask(returnTaskType, 
                      prev, reason);
    }

    next.delayedResume = false;

    // If the top activity is the resumed one, nothing to do.
    if (mResumedActivity == next 
                && next.state == ActivityState.RESUMED &&
                mStackSupervisor.allResumedActivitiesComplete()) {
        // Make sure we have executed any pending transitions, 
        // since there
        // should be nothing left to do at this point.
        mWindowManager.executeAppTransition();
        mNoAnimActivities.clear();
        ActivityOptions.abort(options);
        if (DEBUG_STACK) mStackSupervisor
            .validateTopActivitiesLocked();
        return false;
    }

    final TaskRecord nextTask = next.task;
    if (prevTask != null && prevTask.stack == this &&
            prevTask.isOverHomeStack() && prev.finishing 
            && prev.frontOfTask) {
        if (DEBUG_STACK)  
            mStackSupervisor.validateTopActivitiesLocked();
        if (prevTask == nextTask) {
            prevTask.setFrontOfTask();
        } else if (prevTask != topTask()) {
            // This task is going away but it was supposed to return
            // to the home stack.
            // Now the task above it has to return to the home 
            // task instead.
            final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
            mTaskHistory.get(taskNdx)
                .setTaskToReturnTo(HOME_ACTIVITY_TYPE);
        } else if (!isOnHomeDisplay()) {
            return false;
        } else if (!isHomeStack()){
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Launching home next");
            final int returnTaskType = 
                    prevTask == null || !prevTask.isOverHomeStack() ?
                    HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
            return isOnHomeDisplay() &&
                    mStackSupervisor.resumeHomeStackTask(r
                        eturnTaskType, prev, "prevFinished");
        }
    }

    // If we are sleeping, and there is no resumed activity, and the top
    // activity is paused, well that is the state we want.
    if (mService.isSleepingOrShuttingDownLocked()
            && mLastPausedActivity == next
            && mStackSupervisor.allPausedActivitiesComplete()) {
        // Make sure we have executed any pending transitions, 
        // since there
        // should be nothing left to do at this point.
        mWindowManager.executeAppTransition();
        mNoAnimActivities.clear();
        ActivityOptions.abort(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Going to sleep and all paused");
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return false;
    }

    // Make sure that the user who owns this activity is started.  If not,
    // we will just leave it as is because someone should be bringing
    // another user's activities to the top of the stack.
    if (!mService.mUserController.hasStartedUserState(next.userId)) {
        Slog.w(TAG, "Skipping resume of top activity " + next
                + ": user " + next.userId + " is stopped");
        if (DEBUG_STACK) 
            mStackSupervisor.validateTopActivitiesLocked();
        return false;
    }

    // The activity may be waiting for stop, but that is no longer
    // appropriate for it.
    mStackSupervisor.mStoppingActivities.remove(next);
    mStackSupervisor.mGoingToSleepActivities.remove(next);
    next.sleeping = false;
    mStackSupervisor.mWaitingVisibleActivities.remove(next);

    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

    mActivityTrigger.activityResumeTrigger(next.intent, next.info,
         next.appInfo);

    // If we are currently pausing an activity, then don't do anything
    // until that is done.
    if (!mStackSupervisor.allPausedActivitiesComplete()) {
        if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) 
            Slog.v(TAG_PAUSE,
                "resumeTopActivityLocked: Skip resume: some activity pausing.");
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return false;
    }

    mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

    /**
      * 此时的逻辑进入这里 开始pause当前的activity
      */
    // We need to start pausing the current activity so the 
    // top one can be resumed...
    final boolean dontWaitForPause = 
          (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
    boolean pausing =
         mStackSupervisor.pauseBackStacks(userLeaving, 
          true, dontWaitForPause);
    log("mResumedActivity: "+mResumedActivity);
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " 
                + mResumedActivity);
        log("startPausingLocked");
        /*
         * 进入这里
         */
        pausing |= startPausingLocked(userLeaving, false, true, 
            dontWaitForPause);
    }
    /*
      * log打印返回结果为true
      */
    log("pausing: "+pausing);
    if (pausing) {
        // At this point we want to put the upcoming activity's process
        // at the top of the LRU list, since we know we will be needing it
        // very soon and it would be a waste to let it get killed if it
        // happens to be sitting towards the end.
        if (next.app != null && next.app.thread != null) {
            mService.updateLruProcessLocked(next.app, true, null);
        }
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    } else if (mResumedActivity == next 
          && next.state == ActivityState.RESUMED &&
            mStackSupervisor.allResumedActivitiesComplete()) {
        // It is possible for the activity to be resumed when we paused back 
        // stacks above if the
        // next activity doesn't have to wait for pause to complete.
        // So, nothing else to-do except:
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        mWindowManager.executeAppTransition();
        mNoAnimActivities.clear();
        ActivityOptions.abort(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: "
                +"Top activity resumed (dontWaitForPause) " + next);
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }
    .... (省略一大段代码)
}

接下来进入ActivityStack类中startPausingLocked()方法。

/**
 * Start pausing the currently resumed activity.  It is an error to c
 * all this if there
 * is already an activity being paused or there is no resumed activity.
 * 开始pausing当前resumed activity。这是一个错误去调用如果这里这个activity 
 * 已经paused或者这里没有resumed activity。
 *
 * @param userLeaving True if this should result in an onUserLeaving 
 *         to the current activity.
 * @param uiSleeping True if this is happening with the user 
 *        interface going to sleep (the
 * screen turning off).
 * @param resuming True if this is being called as part of 
 *        resuming the top activity, so
 * we shouldn't try to instigate a resume here.
 * @param dontWait True if the caller does not want to wait for 
 * the pause to complete.  If
 * set to true, we will immediately complete the pause here 
 * before returning.
 * @return Returns true if an activity now is in the PAUSING state, 
 * and we are waiting for
 * it to tell us when it is done.
 */
 final boolean startPausingLocked(boolean userLeaving, 
          boolean uiSleeping, boolean resuming,
         boolean dontWait) {
     log("method called startPausingLocked()");
     log("userLeaving : "+userLeaving); //true
     log("uiSleeping : "+uiSleeping); //false
     log("resuming : "+resuming); //false
     log("dontWait : "+dontWait); //true
      //mPausingActivity is null
     log("mPausingActivity : "+mPausingActivity); 
     if (mPausingActivity != null) {
         Slog.wtf(TAG, 
            "Going to pause when pause is already pending for " 
              + mPausingActivity
                 + " state=" + mPausingActivity.state);
         if (!mService.isSleepingLocked()) {
             // Avoid recursion among check for sleep and complete 
             // pause during sleeping.
             // Because activity will be paused immediately after resume,
             // just let pause
             // be completed by the order of activity paused from clients.
             completePauseLocked(false);
         }
     }

     log("mResumedActivity : "+mResumedActivity); 
    //mResumedActivity -> ActivityRecord{
    //  b5e0db6 u0 com.tct.launcher/.Launcher t22}
     ActivityRecord prev = mResumedActivity;
     if (prev == null) {
         if (!resuming) {
             Slog.wtf(TAG, "Trying to pause when nothing is resumed");
             mStackSupervisor.resumeFocusedStackTopActivityLocked();
         }
         return false;
     }
     // mActivityContainer : ActivtyContainer{0}A
     log("mActivityContainer : "+mActivityContainer);
     // mActivityContainer.mParentActivity : null
     log("mActivityContainer.mParentActivity : "
          +mActivityContainer.mParentActivity);
     if (mActivityContainer.mParentActivity == null) {
         // Top level stack, not a child. Look for child stacks.
         mStackSupervisor.pauseChildStacks(prev, userLeaving, 
              uiSleeping, resuming, dontWait);
     }
     mActivityTrigger.activityPauseTrigger(prev.intent, 
          prev.info, prev.appInfo);

     mResumedActivity = null;
     mPausingActivity = prev;
     mLastPausedActivity = prev;
     mLastNoHistoryActivity = (prev.intent.getFlags() 
            & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
             || (prev.info.flags
             & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
     prev.state = ActivityState.PAUSING;
     prev.task.touchActiveTime();
     clearLaunchTime(prev);
     final ActivityRecord next = 
          mStackSupervisor.topRunningActivityLocked();
     if (mService.mHasRecents
             && (next == null || next.noDisplay
              || next.task != prev.task || uiSleeping)) {
         prev.mUpdateTaskThumbnailWhenHidden = true;
     }
     stopFullyDrawnTraceIfNeeded();

     mService.updateCpuStats();

     if (prev.app != null && prev.app.thread != null) {
        //ProcessRecord{a5a1e38 3184:com.tct.launcher/u0a112}
         log("prev.app: "+prev.app);
        //android.app.ApplicationThreadProxy
         log("prev.app.thread : "
            +prev.app.thread.getClass().getName()); 
        //android.app.ApplicationThreadProxy@fa06d84
         log("prev.app.thread: "+prev.app.thread); 
         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, 
              "Enqueueing pending pause: " + prev);
         try {
             EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                     prev.userId, System.identityHashCode(prev),
                     prev.shortComponentName);
             mService.updateUsageStats(prev, false);
             /**
               * 实际调用ApplicationThreadProxy中
               * 的schedulePauseActivity进行处理
               */
             prev.app.thread.schedulePauseActivity(prev.appToken,
                     prev.finishing,
                     userLeaving, prev.configChangeFlags, dontWait);
         } catch (Exception e) {
             // Ignore exception, if process died other code will cleanup.
             Slog.w(TAG, "Exception thrown during pause", e);
             mPausingActivity = null;
             mLastPausedActivity = null;
             mLastNoHistoryActivity = null;
         }
     } else {
         mPausingActivity = null;
         mLastPausedActivity = null;
         mLastNoHistoryActivity = null;
     }

     // If we are not going to sleep, we want to ensure the device is
     // awake until the next activity is started.
     if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
         mStackSupervisor.acquireLaunchWakelock();
     }

     if (mPausingActivity != null) {
         // 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();
         } else if (DEBUG_PAUSE) {
              Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
         }

         if (dontWait) {
             // If the caller said they don't want to wait for the pause,
            // then complete
             // the pause now.
             completePauseLocked(false);
             return false;

         } else {
             // Schedule a pause timeout in case the app doesn't respond.
             // We don't give it much time because this directly impacts the
             // responsiveness seen by the user.
             Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
             msg.obj = prev;
             prev.pauseTime = SystemClock.uptimeMillis();
             mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, 
                  "Waiting for pause to complete...");
             return true;
         }

     } else {
         // This activity failed to schedule the
         // pause, so just treat it as being paused now.
         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, 
              "Activity not running, resuming next.");
         if (!resuming) {
             mStackSupervisor.resumeFocusedStackTopActivityLocked();
         }
         return false;
     }
 }

进入ApplicationThreadProxy类中的schedulePauseActivity方法。

 public final void schedulePauseActivity(IBinder token,
         boolean finished,boolean userLeaving, int configChanges,
         boolean dontReport) throws RemoteException {
     Parcel data = Parcel.obtain();
     data.writeInterfaceToken(IApplicationThread.descriptor);
     data.writeStrongBinder(token);
     data.writeInt(finished ? 1 : 0);
     data.writeInt(userLeaving ? 1 :0);
     data.writeInt(configChanges);
     data.writeInt(dontReport ? 1 : 0);
     //Binder通信
     mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, 
        data, null,
             IBinder.FLAG_ONEWAY);
     data.recycle();

又开始调用Binder进行进程间通信。Binder执行流程与前文一样,略过.....

  1. android framework中有些类和方法实在是太庞大了,动不动就上千行一个类,几百行一个方法。

    回复