Activity 启动流程,源码分析

转载请注明出处

用户在 桌面点击一个App Icon的时候,系统如何启动这个应用的Activity。

不管是activity.startActivity(),还是通过context.startActivity(),`这里写代码片
最终都会走到

            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity)null, intent, -1, options);

简单描述一下mainThread,其实就是ActivityThread。
ActivityThread 职能其实简单点说,在Application中,通过

Looper.prepareMainLooper();
......
Looper.loop();

将process中的主线程绑定出来。平时大家在主线程里面new 出来的handler,发送的msg都是到了这个 主线程中的looper中的,所以执行的时候,都是在主线程执行的。

ActivityThread 另外的职能在于管理本进程中所有的acitivity,并处理来自于 app进程和系统进程之间服务的 调用,例如接收系统的广播,向系统发送activity 的request。

继续看activity的启动

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
     。。。。。
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }

只看主要部分,兜兜转转,启动activity的主要职责还是回到了ActivityManagerNative,
checkStartActivityResult(),函数只是用于对系统启动activity出错的返回值进行处理,抛出异常。

ActivityManagerNative 这个类理解起来非常容易,直接把它当做 ActivityManagerService在本地的代理就行,它存在的意义就是在App process和ActivityManagerService的通信。

其实就是代理类。。。。

ActivityManagerNative 中通过

    private IBinder mRemote;

mRemote 向远端的 ActivityManagerService 发出请求

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

其实你会发现ActivityManagerService 是ActivityManagerNative 的 子类,因为ActivityManagerNative 的主要职责就是 做接口的代理,也就是说,只是远端和本地 不同process的接口交互。

真正执行startactivity方法的类,只在ActivityManagerService。


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

handleIncomingUser(),简单点理解只是为了 做userid的校验。

mStackSupervisor,这个成员变量挺重要的,ActivityStackSupervisor 它保存了所有系统中所有启动的activity的状态和生命周期,包括task栈的管理。

现在来一行一行看这个函数里面干了些什么

   final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        boolean componentSpecified = intent.getComponent() != null;

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

        // 通过intent制定的acitivty去查找相应的manifest里面查找 相关信息,例如启动模式啊,等等的配置得到info
        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                profilerInfo, userId);

      //略过,一些状态的校验
      。。。。。


       //继续走start流程
            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options,
                    componentSpecified, null, container, inTask);

            Binder.restoreCallingIdentity(origId);


            return res;
        }
    }

startActivityLocked 函数

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


//先查找 caller App ,根据起userid 查询其是否有权限。
        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;
            }
        }

      。。。。。

从intent中获取出 启动目标activity 配置的flag 例如 cleartop相类似的启动行为的flags
        final int launchFlags = intent.getFlags();

//这里就是在标记 startactivityforresult 标记出 目标activity回传的intent是给谁的
        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;
            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 && 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 & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
                try {
                    if (!AppGlobals.getPackageManager().activitySupportsIntent(
                            intent.getComponent(), intent, resolvedType)) {
                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                    }
                } catch (RemoteException e) {
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            }
        }

     //对某些特殊的activity session做处理,这里不深入

      //然后就是各种各样的权限检查
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, this, container, options);
        if (outActivity != null) {
            outActivity[0] = r;
        }

        final ActivityStack stack = getFocusedStack();
        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);


          //注意  
          //注意 
          //注意 
          //这里是将 构造好的activityinfo 加入到pending 的队列里面去。并不是说我在本地调用了startactivity,就
          //立马执行的
                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;
        }


     //如果堆栈里面前面排有了其他的activity,是按照队列的方式执行的
     //如果里面的队列是空得化,就继续往下走。
        doPendingActivityLaunchesLocked(false);

        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

        if (err < 0) {
            // If someone asked to have the keyguard dismissed on the next
            // activity start, but we are not actually doing an activity
            // switch...  just dismiss the keyguard now, because we
            // probably want to see whatever is behind it.
            notifyActivityDrawnForKeyguard();
        }
        return err;
    }

startActivityUncheckedLocked()函数
最最最核心的代码来了。

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

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

      //通过上面收集到得 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;

//又是一大段的if else 也是在做 启动模式的梳理,和result 传递的处理


 //又是一大段,对activity的配置,决定这个activity是否是在原有的task栈中


//又是一大段代码,决定这个activity是否是新开一个task栈,有兴趣的话可以继续看看 newtask 是如何弄出来的。

//还有一大段代码就是在做 activity的四种启动模式

       targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        if (!launchTaskBehind) {
            // Don't set focus on an activity that's going to the back.
            mService.setFocusedActivityLocked(r, "startedActivity");
        }
        return ActivityManager.START_SUCCESS;
    }

这个函数主要是通知WindowManager,这个acitivity 被创建出来了,需要向你注册,以后有啥事件或者动画的话也需要你来分发和管理。
startActivityLocked()

         。。。。。
//简单点来看这个函数就是 将activity 这个window 申请token,以便于得到mWindowManager的管理         
mWindowManager.addAppToken(task.mActivities.indexOf(r),
                    r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                    (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
                    r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
。。。。。

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

 又回到了mStackSupervisor
resumeTopActivitiesLocked()
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
        Bundle targetOptions) {
    if (targetStack == null) {
        targetStack = getFocusedStack();
    }
    // Do targetStack first.
    boolean result = false;

//找到栈顶的task 在找到这个task栈的 最上层的activity
if (isFrontStack(targetStack)) {
result = resumeTopActivityLocked(prev, options);
}
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; –displayNdx) {
final ArrayList stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; –stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack == targetStack) {
// Already started above.
continue;
}
if (isFrontStack(stack)) {
stack.resumeTopActivityLocked(null);
}
}
}
return result;
}


resumeTopActivityLocked()-》resumeTopActivityInnerLocked()

resumeTopActivityInnerLocked()
{
//前面代码略过
//简单说一下前面代码做的事情。
//1,在task 栈里面 找是否有存在 承载此acitivity的栈,并更改栈的指针

       if (next.app != null && next.app.thread != null) {
     //找到此 task栈 windowmanager 对此App注册,病切换到前台显示
                 mWindowManager.setAppVisibility(next.appToken, true);
    。。。。。。

    //在这个App的 activitythread 里面去 将这个activity启动起来,就是前面简单分析的activityThread
                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        next.state = lastState;
                }
//如果这个activity 没有一个task栈去承载,并且是 新的application 则 调用此方法

else {
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
}



startSpecificActivityLocked()启动进程并且去承载此应用

void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {

//找相关进程,看是否存活在
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);

        // 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);
}
“`

//差不多到这里,普通的activity启动流程已经结束。

//特殊的activity还在继续,再往后面的话,差不多就是进程的启动了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值