Activity的启动过程(2)

Activity启动流程(1)中,Activity的启动经过binder通信就会进入ActivityManagerService所在的进程中继续执行startActivity方法,由于后续的方法涉及的逻辑比较多,在后面的分析中我可能会把某一个函数单独拿出来分析,最后我会做一个启动流程的总结。
ok,接下来看下startActivity的实现:

ActivityManangerService类startActivity

public final int startActivity(IApplicationThread caller,
        Intent intent, String resolvedType, Uri[] grantedUriPermissions,
        int grantedMode, IBinder resultTo,
        String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
        String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
    return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
            grantedUriPermissions, grantedMode, resultTo, resultWho,
            requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
            null, null);
}  

可以发现,这一步其实什么操作都没有做,只是将调用转发给了mMainStack,然后执行了startActivityMayWait方法。如果对参数的值记得不是很清晰的,可以看下Activity的启动流程(1)

接下来就要真的开始真正进入分析正题了。ActivityStack.java位于的源码路径为frameworks/base/services/java/com/android/server/am/ActivityStack.java,看下mStack.startActivityMayWait:

ActivityStack类startActivityMayWait

final int startActivityMayWait(IApplicationThread caller, int callingUid,
        Intent intent, String resolvedType, Uri[] grantedUriPermissions,
        int grantedMode, IBinder resultTo,
        String resultWho, int requestCode, boolean onlyIfNeeded,
        boolean debug, String profileFile, ParcelFileDescriptor profileFd,
        boolean autoStopProfiler, WaitResult outResult, Configuration config) {
    // Refuse possible leaked file descriptors
    if (intent != null && intent.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }
    /**intent.getComponent != null componentSpecified = true*/
    boolean componentSpecified = intent.getComponent() != null;

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

    // Collect information about the target of the Intent.
    /**获得即将启动的activity的信息*/
    ActivityInfo aInfo = resolveActivity(intent, resolvedType, debug,
            profileFile, profileFd, autoStopProfiler);

    /**启动activity时对ActivityManagerService作同步*/
    synchronized (mService) {
        int callingPid;
        if (callingUid >= 0) {
            callingPid = -1;
        } else if (caller == null) {
            callingPid = Binder.getCallingPid();
            callingUid = Binder.getCallingUid();
        } else {
            callingPid = callingUid = -1;
        }
        //callingPid = callingUid = -1
        mConfigWillChange = config != null
                && mService.mConfiguration.diff(config) != 0;
        if (DEBUG_CONFIGURATION) Slog.v(TAG,
                "Starting activity when config will change = " + mConfigWillChange);
        //mConfigWillChange = false
        //清除调用者的pid和uid,准备调用本进程内的函数 
        final long origId = Binder.clearCallingIdentity();
        /**mMainStack在ActivityManangerService创建ActivityStack实例时被赋值为true*/
        if (mMainStack && aInfo != null &&
                (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
            ......
        }

        int res = startActivityLocked(caller, intent, resolvedType,
                grantedUriPermissions, grantedMode, aInfo,
                resultTo, resultWho, requestCode, callingPid, callingUid,
                onlyIfNeeded, componentSpecified, null);

        ......
}

这部分还是比较好理解的,我把和流程无关紧要的代码注释掉了。intent.getComponent() != null,故componentSpecified = true;接下来就是调用resolveActivity方法获取即将启动的Activity信息aInfo,aInfo的信息主要是从AndroidManifest.xml中获取,resolveActivity的具体实现,可以参考resolveActivity解析;接下来会设置callingUid和callingPid,从上一步可知,callingUid为-1且caller != null,故最后得到callingPid = callingUid = -1;config = null,故mConfigWillChange = false。接下来就会进入startActivityLocked函数。

ActivityStack类startActivityLocked

final int startActivityLocked(IApplicationThread caller,
        Intent intent, String resolvedType,
        Uri[] grantedUriPermissions,
        int grantedMode, ActivityInfo aInfo, IBinder resultTo,
        String resultWho, int requestCode,
        int callingPid, int callingUid, boolean onlyIfNeeded,
        boolean componentSpecified, ActivityRecord[] outActivity) {

    int err = START_SUCCESS;
    ProcessRecord callerApp = null;
    /**根据传入的IApplicationThread构建应用的ProcessRecord*/
    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 = START_PERMISSION_DENIED;
        }
    }

    if (err == START_SUCCESS) {
        Slog.i(TAG, "START {" + intent.toShortString(true, true, true) + "} from pid "
                + (callerApp != null ? callerApp.pid : callingPid));
    }

    ActivityRecord sourceRecord = null;
    ActivityRecord resultRecord = null;
    if (resultTo != null) {
        int index = indexOfTokenLocked(resultTo);
        if (DEBUG_RESULTS) Slog.v(
            TAG, "Will send result to " + resultTo + " (index " + index + ")");
        if (index >= 0) {
            /**requestCode >= 0表示需要启动的Actvity给父Activity返回结果,故sourceRecord和resultRecode相同*/
            sourceRecord = mHistory.get(index);
            if (requestCode >= 0 && !sourceRecord.finishing) {
                resultRecord = sourceRecord;
            }
        }
    }
    /**resultRecord = null*/
    int launchFlags = intent.getFlags();

    if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
            && sourceRecord != null) {
       ......
    }
    //代码块1
    /**未找到要启动的Activity组建信息*/
    if (err == START_SUCCESS && intent.getComponent() == null) {
        // We couldn't find a class that can handle the given Intent.
        // That's the end of that!
        err = START_INTENT_NOT_RESOLVED;
    }

    //代码块2
    /**根据提供的条件,未解析成功Activty信息*/
    if (err == START_SUCCESS && aInfo == null) {
        // We couldn't find the specific class specified in the Intent.
        // Also the end of the line.
        err = START_CLASS_NOT_FOUND;
    }
    //代码块3
    if (err != START_SUCCESS) {
        if (resultRecord != null) {
            sendActivityResultLocked(-1,
                resultRecord, resultWho, requestCode,
                Activity.RESULT_CANCELED, null);
        }
        mDismissKeyguardOnNextActivity = false;
        return err;
    }

    //代码块4
    /**检查启动Activity进行的权限信息*/
    final int perm = mService.checkComponentPermission(aInfo.permission, callingPid,
            callingUid, aInfo.applicationInfo.uid, aInfo.exported);
    if (perm != PackageManager.PERMISSION_GRANTED) {
       ......
    }

    ......

    ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
            intent, resolvedType, aInfo, mService.mConfiguration,
            resultRecord, resultWho, requestCode, componentSpecified);
   ......

    err = startActivityUncheckedLocked(r, sourceRecord,
            grantedUriPermissions, grantedMode, onlyIfNeeded, true);
    ......
    return err;
}  

这部分代码理解起来不复杂,我在代码中也进行了注视。startActivityLocked函数的主要作用就是构建ActivityRecord信息,准备为下一步Activity Task的创建和复用做准备。函数一开始根据启动目标Activity的进程(由于我们是在手机桌面启动了应用)构建ProcessRecord,这里的ProcessRecord指向就是Launcher所在的进程;接着使用构建的ProcessRecord callerApp获取callingUid和callingPid,如果记得清楚的话,在此步骤之前,callingUid和callingPid一直为-1,到了这一步才被真正赋值;尝试获取sourceRecord和resultRecord,mHistory保存所有之前启动过的Activity,由于Launcher已经启动,故sourceRecord表示Launcher,由于requestCode = -1故resultRecord=null;代码块1会判断能否根据intent找到要启动的Activity的组建信息,如果未找到,则err = START_INTENT_NOT_RESOLVED;代码块2会判断能否解析要启动的Activity信息,如果不能解析,则err = START_CLASS_NOT_FOUND;代码块3判断经过前面的判断之后,如果err != START_SUCCESS,则返回错误码。

进过上面的处理后,系统会去判断启动此Activity的进程的权限,如果未能通过验证,则会返回权限异常,权限部分会在后续文章中进行分析。过程中还有其他无关流程的处理我就省略掉了,接下来就会根据之前的信息构造即将要启动的Activity的ActivityRecord,然后去调用startActivityUncheckedLocked

ActivityStack类startActivityUncheckedLocked

final int startActivityUncheckedLocked(ActivityRecord r,
        ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
        int grantedMode, boolean onlyIfNeeded, boolean doResume) {
    final Intent intent = r.intent;
    final int callingUid = r.launchedFromUid;

    int launchFlags = intent.getFlags();

    // We'll invoke onUserLeaving before onPause only if the launching
    // activity did not explicitly state that this is an automated launch.
    //代码块1
    mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;

由于要启动的Activity未置位Intent.FLAG_ACTIVITY_NO_USER_ACTION,故mUserLeaving = true。

    if (!doResume) {
       ......
    }
    //r.delayResume = true
    ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
            != 0 ? r : null;
    //notTop = null
    // If the onlyIfNeeded flag is set, then we can do this if the activity
    // being launched is the same as the one making the call...  or, as
    // a special case, if we do not know the caller then we count the
    // current top activity as the caller.
    if (onlyIfNeeded) {
       ......
    }

    if (sourceRecord == null) {
       ......
    } 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.
        //代码块1
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
  }   else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
        // The activity being started is a single instance...  it always
        // gets launched into its own task.
        //代码块2
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    }

    if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
              ......
              //代码块3
    }
    boolean addingToTask = false;
    TaskRecord reuseTask = null;
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
            (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
         //代码块4
       if (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 taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                    ? findTaskLocked(intent, r.info)
                    : findActivityLocked(intent, r.info);
            if (taskTop != null) {
               ......
               //代码块5
             }
    }

从前面的分析可知,doResue = true,notTop = null;onlyIfNeeded = false;sourceRecord != null;代码块1会对sourecRecord的launchMode进行判断,由于sourceRecord代表的是Launcher,Launcher的launchMode为SINGLE_INSTANCE,故在代码块1会对launchFlags添加Intent.FLAG_ACTIVITY_NEW_TASK的标志。代码块2会对即将启动的Activity的launchMode进行判断,由于我们在新建Activity时并没有执行launchMode,launchMode为STAND,故不会进入代码块2执行;由之前的分析可知r.resultTo = null,故代码块3也不会执行;由于在代码块1中LAUNCH_SINGLE_TASK被置位,个程序会进入代码块4中执行;根据之前的分析r.resultTo = null,由于r.launchMode != LAUNCH_SINGLE_INSTANCE,故程序会执行findTaskLocked函数,并将结果赋值给taskTop,由于即将要启动的Activity的launchMode被设置为LAUNCH_SINGLE_TASK,故在系统中中无法找到可以启动目标Activity的ActivityRecord,故taskTop = null,故代码块5不会被执行

    boolean newTask = false;
    boolean keepCurTransition = false;

    // Should this be considered a new task?
    if (r.resultTo == null && !addingToTask
            && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        if (reuseTask == null) {
            //代码块1
            // todo: should do better management of integers.
            mService.mCurTask++;
            if (mService.mCurTask <= 0) {
                mService.mCurTask = 1;
            }
            r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                    + " in new task " + r.task);
        } else {
            r.setTask(reuseTask, reuseTask, true);
        }
        newTask = true;
       .....

    } else if (sourceRecord != null) {
        //代码块2
       ......
    } else if (!addingToTask &&
                (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
      //代码块3
       ......

    } else {
     //代码块4
       ......
    }

   ......
   startActivityLocked(r, newTask, doResume, keepCurTransition);  

根据前面的分析可知,r.resultTo = null ,addingToTask = false且launchFlags的FLAG_ACTIVITY_NEW_TASK被置为,故代码块1会被执行,代码块2,3,4均不会被执行,接下来就好好分析下代码块1。

经过之前的分析可知,需要心的Activity Task来启动目标Activity,mService为ActivityManagerService实例,mCurTask表示当前task的数量,在新建task之前先修改mCurTask的值,使其加1,然后为目标Activity的ActivityRecord设置新的的TaskRecord,并设置newTask = true,接下来就会去执行startActivityLocked函数了,这个startActivityLocked函数是之前startActivity函数的重载形式。

ActivityStack类startActivityLocked

private final void startActivityLocked(ActivityRecord r, boolean newTask,
        boolean doResume, boolean keepCurTransition) {
    final int NH = mHistory.size();
    int addPos = -1;
    if (!newTask) {
        //代码块1
        .......
    }
    if (addPos < 0) {
        addPos = NH;
    }
    if (addPos < NH) {
       ......
    }
    mHistory.add(addPos, r);
    r.putInHistory();
    r.frontOfTask = newTask;
    if (NH > 0) {
        ......
    } else {
        ......
    }
    if (VALIDATE_TOKENS) {
        ......
    }

    if (doResume) {
        resumeTopActivityLocked(null);
    }
}  

这块代码还是比较容易理解的,这部分代码的主要作用是对window进行相应的处理,有兴趣的亲可以自己去研究下。由于很多代码不影响Activity的启动流程,故代码里面就直接省略了。由于doResume = true,故接下来代码将会进入resumeTopActivityLocked逻辑。

ActivityStack类resumeTopActivityLocked

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

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

    if (next == null) {
        ......
    }

    next.delayedResume = false;

    // If the top activity is the resumed one, nothing to do.
    if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
        ......
    }

    // 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.mSleeping || mService.mShuttingDown)
            && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        ......
    }

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

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

    // If we are currently pausing an activity, then don't do anything
    // until that is done.
    if (mPausingActivity != null) {
        if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
        return false;
    }

    // Okay we are now going to start a switch, to 'next'.  We may first
    // have to pause the current activity, but this is an important point
    // where we have decided to go to 'next' so keep track of that.
    // XXX "App Redirected" dialog is getting too many false positives
    // at this point, so turn off for now.
    if (false) {
        ......
    }

    // We need to start pausing the current activity so the top one
    // can be resumed...
    if (mResumedActivity != null) {
        if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
        startPausingLocked(userLeaving, false);
        return true;
    }
    ......
}  

dd这部分代码也很好理解。 next保存着即将启动的目标Activity,由前面的分析可以,mUserLeaving = true,这里使用userLeaving保存mUserLeaving,然后重置mUserLeaving的值为false;mResumedActivity表示Launcher;mLastPausedActivity表示系统休眠时,栈顶的Activity;由于当前系统未处于休眠状态,故代码的执行逻辑会走到startPausingLocked

ActivityStack类startPausingLocked

private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
    if (mPausingActivity != null) {
        RuntimeException e = new RuntimeException();
        Slog.e(TAG, "Trying to pause when pause is already pending for "
              + mPausingActivity, e);
    }
    ActivityRecord prev = mResumedActivity;
    if (prev == null) {
        RuntimeException e = new RuntimeException();
        Slog.e(TAG, "Trying to pause when nothing is resumed", e);
        resumeTopActivityLocked(null);
        return;
    }
    if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
    else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
    mResumedActivity = null;
    mPausingActivity = prev;
    mLastPausedActivity = prev;
    prev.state = ActivityState.PAUSING;
    prev.task.touchActiveTime();
    prev.updateThumbnail(screenshotActivities(prev), null);

    mService.updateCpuStats();

    if (prev.app != null && prev.app.thread != null) {
        if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
        try {
           ......
            prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
                    prev.configChangeFlags);
            ......
        } catch (Exception e) {
           ......
        }
    } else {
        ......
}
......  

startPausingLocked的主要工作就是让当前正处于resume状态的Activity执行onPause函数然后转换为pause状态。mResumedActivity指向的是Launcher,接着使用pre保存mResumedActivity,接下来利用prev.app.thread.schedulePauseActivity函数让Launcher进行状态转换,进入pause状态,接下来就需要进入Launcher进程进行函数分析了,ActivityManangerService的工作暂时告一段落,ActivityManagerService会等待Launcher进程通知自己已经pause完成,然后ActivityManagerService再进行其他操作。下面的分析我会新启一篇。

猜你喜欢

转载自blog.csdn.net/rockstore/article/details/79749304