http://blog.csdn.net/turkeycock/article/details/50538971
最近由于工作需要,需要深入了解AMS的内部实现。说老实话,虽然已经经过了几轮重构,AMS的代码还是又臭又长。。。
万事开头难,先找个入口开始看吧。当从Launcher界面点击启动一个app时,会启动一个新的activity。所以就从startActivity()看起,研究一下activity启动的整个流程。
虽然代码很长,大体上还是有个一个脉络的,参见下图:
这样是不是感觉清楚很多?基本上分为下面这些步骤:
- 创建相关的数据结构并建立联系(ActivityRecord, ActivityStack, TaskRecord等等)
- Pause前一个activity(这里指的就是Launcher)
- 创建新进程,启动新的ActivityThread
- 传递binder通信对象,创建Activity并调用其onCreate()方法
下面详细分析一下相关代码(基于android 5.1):
- public void startActivity(Intent intent, @Nullable Bundle options) {
- if (options != null) {
- startActivityForResult(intent, -1, options);
- } else {
-
-
- startActivityForResult(intent, -1);
- }
- }
Activity调用Instrumentation去启动新的activity:
- public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
- ... ...
- Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
- this, mMainThread.getApplicationThread(), mToken, this,
- intent, requestCode, options);
- ... ...
- }
Instrumentation通过binder将请求发送到远端的ActivityManagerService。ActivityManagerNative.getDefault()返回的是一个IActivityManager接口,后面会详细讲解这个接口是怎么和远端联系起来的。
- public ActivityResult execStartActivity(
- Context who, IBinder contextThread, IBinder token, Fragment target,
- Intent intent, int requestCode, Bundle options) {
- ... ...
- int result = ActivityManagerNative.getDefault()
- .startActivity(whoThread, who.getBasePackageName(), intent,
- intent.resolveTypeIfNeeded(who.getContentResolver()),
- token, target != null ? target.mWho : null,
- requestCode, 0, null, options);
- ... ...
- }
- static public IActivityManager getDefault() {
- return gDefault.get();
- }
- private static final Singleton gDefault = new Singleton() {
- protected IActivityManager create() {
- IBinder b = ServiceManager.getService("activity");
- if (false) {
- Log.v("ActivityManager", "default service binder = " + b);
- }
- IActivityManager am = asInterface(b);
- return am;
- }
- }
先看一下Java Binder的一般结构:
左半边是server端的具体实现,右半边是client端使用的代理。这样一来就很清楚了,IActivityManager必定有一个ActivityManagerProxy的代理类,里面包含了一个BinderProxy对象来和远端通信。远端也必定有一个ActivityManagerNative的类负责响应binder请求,同时有一个子类来完成具体的业务逻辑,这个类就是ActivityManagerService。具体类图如下:
这里谈到了ActivityManagerService,那我们就先来看一下它是怎么启动的。
ActivityManagerService是在SystemServer里通过SystemServiceManager的startService()方法启动的,传入的参数是一个叫Lifecycle的内部类。该方法会利用反射的方式,根据类名获取其构造函数,创建对象实例,最后调用service的onStart()方法。
-
- mActivityManagerService = mSystemServiceManager.startService(
- ActivityManagerService.Lifecycle.class).getService();
-
- public extends SystemService> T startService(Class serviceClass) {
- ... ...
- Constructor constructor = serviceClass.getConstructor(Context.class);
- service = constructor.newInstance(mContext);
- ... ...
-
- mServices.add(service);
-
- service.onStart();
- ... ...
- }
看一眼Lifecycle类,该类继承自SystemService,构造函数里会创建ActivityManagerService实例,onStart()里会调用ActivityManagerService的start()方法。
- public static final class Lifecycle extends SystemService {
- private final ActivityManagerService mService;
-
- public Lifecycle(Context context) {
- super(context);
- mService = new ActivityManagerService(context);
- }
-
- @Override
- public void onStart() {
- mService.start();
- }
-
- public ActivityManagerService getService() {
- return mService;
- }
- }
仅仅启动ActivityManagerService是不够的,外面的人怎么来访问它呢?显然需要把ActivityManagerService注册到ServiceManager里,这一步也是在SystemService里完成的:
- private void startBootstrapServices() {
- ... ...
-
- mActivityManagerService.setSystemProcess();
- ... ...
- }
-
- public void setSystemProcess() {
- ... ...
- ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
- ... ...
- }
再回到之前的话题,我们通过binder 远程调用ActivityManagerService的startActivity()方法:
- public final int startActivity(IApplicationThread caller, String callingPackage,
- Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle options) {
- return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
- resultWho, requestCode, startFlags, profilerInfo, options,
- UserHandle.getCallingUserId());
- }
-
- 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");
- ... ...
- return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
- resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- profilerInfo, null, null, options, userId, null, null);
- }
调用ActivityStackSupervisor的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, WaitResult outResult, Configuration config,
- Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {
- ... ...
- ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
- profilerInfo, userId);
- ... ...
- int res = startActivityLocked(caller, intent, resolvedType, aInfo,
- voiceSession, voiceInteractor, resultTo, resultWho,
- requestCode, callingPid, callingUid, callingPackage,
- realCallingPid, realCallingUid, startFlags, options,
- componentSpecified, null, container, inTask);
- ... ...
- }
resolveActivity()会从PackageManagerService获取目标activity的信息,比如package名、activity名等。然后调用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) {
- ... ...
- ProcessRecord callerApp = null;
- callerApp = mService.getRecordForAppLocked(caller);
- ... ...
- ActivityRecord sourceRecord = null;
- if (resultTo != null) {
- sourceRecord = isInAnyStackLocked(resultTo);
- ... ...
- 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;
- }
- ... ...
- err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
- startFlags, true, options, inTask);
- ... ...
- }
首先获得调用进程的ProcessRecord和ActivityRecord,然后为要启动的activity创建新的ActivityRecord,最后调用startActivityUncheckedLocked()。
- final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
- boolean doResume, Bundle options, TaskRecord inTask) {
- ... ...
- int launchFlags = intent.getFlags();
- ... ...
-
- if (r.resultTo == null && inTask == null && !addingToTask
- && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
- ... ...
- newTask = true;
- targetStack = adjustStackFocus(r, newTask);
- ... ...
- if (reuseTask == null) {
- r.setTask(targetStack.createTaskRecord(getNextTaskId(),
- newTaskInfo != null ? newTaskInfo : r.info,
- newTaskIntent != null ? newTaskIntent : intent,
- voiceSession, voiceInteractor, !launchTaskBehind ),
- taskToAffiliate);
- ... ...
- targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
- ... ...
- }
首先从intent中获取activity的启动模式,如果AndroidManifest.xml中没有显示指定launchMode属性,默认以ActivityInfo.LAUNCH_MULTIPLE的方式启动activity。(其他三种方式是LAUNCH_SINGLE_INSTANCE、LAUNCH_SINGLE_TASK、LAUNCH_SINGLE_TOP)
如果是从Launcher中启动的activity,默认会带有FLAG_ACTIVITY_NEW_TASK的标志,表示需要新建一个task,然后把activity加入到这个task中。
但是在这之前,我们需要先确定要把这个新建的task放到哪个ActivityStack上。ActivityStackSupervisor里会包含两个stack,一个叫mHomeStack,主要用于管理Launcher还有SystemUI Rectent Tasks的activity,另一个叫mFocusedStack,用于管理其他app的activity。如果当前没有其他app在运行,那么就只有mHomeStack,当其他app启动时会动态创建一个新的stack。因此你用“dumpsys activity activities”查看stack状态时,总能看见一个ID为0的stack,而另一个stack的ID是可变的。
首先通过adjustStackFocus()获取目标stack,由于当前是在home stack,因此需要创建一个新的stack,然后让mFocusedStack指向这个新栈。
- ActivityStack adjustStackFocus(ActivityRecord r, boolean newTask) {
- ... ...
- int stackId = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
- ... ...
- mFocusedStack = getStack(stackId);
- return mFocusedStack;
- }
值得一提的是,createStackOnDisplay()并不是直接创建一个ActivityStack,而是创建了一个ActivityContainer对象,ActivityContainer的构造函数里会创建一个ActivityStack。
另外,ActivityContainer是一个binder对象,有一个IActivityContainer.aidl与之对应,可以通过IActivityManager的API创建和删除。所以可以把ActivityContainer理解为ActivityStack的马甲,外部如果想访问ActivityStack,只能通过ActivityContainer暴露的一些binder API。更多关于ActivityContainer的应用后面有一篇关于ActivityView的文章里会详细描述。
接下来就是创建TaskRecord并加入到目标stack的task列表中,并把这个task设置到当前的ActivityRecord中。
- TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- boolean toTop) {
- TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
- voiceInteractor);
- addTask(task, toTop, false);
- return task;
- }
最后调用ActivityStack的startActivityLocked()方法。
- final void startActivityLocked(ActivityRecord r, boolean newTask,
- boolean doResume, boolean keepCurTransition, Bundle options) {
- ... ...
- task.addActivityToTop(r);
- task.setFrontOfTask();
- r.putInHistory();
- ... ...
- if (doResume) {
- mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
- }
- ... ...
- }
首先把activity加入到task中,然后把ActivityRecord中的inHistory标志置上表示该activity已经在栈中了,最后调用ActivityStackSupervisor的resumeTopActivitiesLocked()方法。
- boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
- Bundle targetOptions) {
- ... ...
- result = targetStack.resumeTopActivityLocked(target, targetOptions);
- }
这里主要是为了多个display的处理,一般只有一个显示屏,因此又调回到了ActivityStack里面的resumeTopActivityLocked()。
- final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
- ... ...
- result = resumeTopActivityInnerLocked(prev, options);
- ... ...
- }
- final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
- ... ...
-
- final ActivityRecord next = topRunningActivityLocked(null);
- ... ...
-
-
- if (mResumedActivity != null) {
- pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
- }
- if (pausing) {
- ... ...
- return true;
- }
- ... ...
- }
首先获取栈顶的ActivityRecord,就是我们要启动的新activity,因为上一步我们已经把要启动的新activity的ActivityRecord(其实是包含它的TaskRecord)加入到栈中了。
mResumedActivity表示当前前台的activity,也就是Launcher activity,调用startPausingLocked()先pause掉这个activity。
- final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
- boolean dontWait) {
- ... ...
- ActivityRecord prev = mResumedActivity;
- ... ...
- mResumedActivity = null;
- mPausingActivity = prev;
- mLastPausedActivity = prev;
- ... ...
- if (prev.app != null && prev.app.thread != null) {
- prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
- userLeaving, prev.configChangeFlags, dontWait);
- }
- ... ...
- }
这一步先获得当前前台activity的ActivityRecord,然后通过它里面包含的IApplicationThread代理对象和远端app(Launcher)进行通信。之前提到过app端可以通过一个IActivityManager代理和ActivityManagerService进行binder IPC通信,反之,ActivityManagerService这端和app端通信时是通过IApplicationThread代理对象完成,或者确切的说是一个ApplicationThreadProxy对象。类图基本和之前类似,在此省略。
下面看看app(Launcher)端是怎么响应这个请求的。每个app进程都拥有一个ActivityThread线程,它的main()函数是整个程序的主入口。ActivityThread内部聚合了一个ApplicationThread对象,用于响应远端的请求。接收到请求后,向looper中投递一个消息,由handler进行处理。
- public final void schedulePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges, boolean dontReport) {
- sendMessage(
- finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
- token,
- (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
- configChanges);
- }
-
- public void handleMessage(Message msg) {
- ... ...
- case PAUSE_ACTIVITY:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
- handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
- (msg.arg1&2) != 0);
- maybeSnapshot();
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- break;
- ... ...
- }
-
- private void handlePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges, boolean dontReport) {
- ActivityClientRecord r = mActivities.get(token);
- ... ...
- performPauseActivity(token, finished, r.isPreHoneycomb());
- ... ...
-
- if (!dontReport) {
- try {
- ActivityManagerNative.getDefault().activityPaused(token);
- } catch (RemoteException ex) {
- }
- }
这里主要进行了3步操作:
第一步根据token获取ActivityClientRecord对象,这个对象是在activity启动时创建的,可以理解为client端的ActivityRecord,复制了一份activity的相关信息。
第二步调用performPauseActivity(),通过Instrumentation对象调用我们熟悉activity生命周期中的onPause()方法。
- final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
- boolean saveState) {
- ... ...
- mInstrumentation.callActivityOnPause(r.activity);
- ... ...
- }
第三步通过IActivityManager代理通知ActivityManagerService本端的activity已经进入paused状态,可以进行下一步操作也就是启动新的activity了。
ActivityManagerSerivce端的响应代码:
- public final void activityPaused(IBinder token) {
- final long origId = Binder.clearCallingIdentity();
- synchronized(this) {
- ActivityStack stack = ActivityRecord.getStackLocked(token);
- if (stack != null) {
- stack.activityPausedLocked(token, false);
- }
- }
- Binder.restoreCallingIdentity(origId);
- }
- final void activityPausedLocked(IBinder token, boolean timeout) {
- ... ...
- completePauseLocked(true);
- ... ...
- }
- private void completePauseLocked(boolean resumeNext) {
- ActivityRecord prev = mPausingActivity;
- if (prev != null) {
- ... ...
- mPausingActivity = null;
- }
- ... ...
- if (resumeNext) {
- final ActivityStack topStack = mStackSupervisor.getFocusedStack();
- if (!mService.isSleepingOrShuttingDown()) {
- mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
- ... ...
- }
- }
这里mPausingActivity在之前的步骤里已经被置成了Launcher,在执行一些其他清理操作之后将其置为null。最后再次调用resumeTopActivitiesLocked()开始启动新的activity。
这次进这个函数,情况已经和之前不同了,mResumedActivity已经被置成了null,因此不会再走进pause activity的逻辑,继续往前执行。
- final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
- ... ...
- final ActivityRecord next = topRunningActivityLocked(null);
- ... ...
- if (next.app != null && next.app.thread != null) {
- ... ...
- } else {
- ... ...
- mStackSupervisor.startSpecificActivityLocked(next, true, true);
- }
- }
- void startSpecificActivityLocked(ActivityRecord r,
- boolean andResume, boolean checkConfig) {
- ... ...
- mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
- "activity", r.intent.getComponent(), false, false, true);
- }
看到startProcessLocked()这个函数,大家应该比较熟悉了,后面就是创建ProcessRecord,fork新的进程,然后执行ActivityThread的main()函数了。
- public static void main(String[] args) {
- ... ...
- ActivityThread thread = new ActivityThread();
- thread.attach(false);
- ... ...
- Looper.loop();
- }
在ActivityThread的main()函数里,首先创建了一个ActivityThread对象,然后调用其attach()方法,最后通过Looper.loop()进入消息循环。
- private void attach(boolean system) {
- ... ...
- if (!system) {
- ... ...
- final IActivityManager mgr = ActivityManagerNative.getDefault();
- try {
- mgr.attachApplication(mAppThread);
- ... ...
- }
- ... ...
- }
通过binder IPC调用到ActivityManagerService的attachApplicationLocked()。注意这里传入的是一个ApplicationThread对象,经过binder传输后ActivityManagerService端会获得该对象的一个代理,之后就可以通过这个代理和app端进行通信了。
- public final void attachApplication(IApplicationThread thread) {
- ... ...
- attachApplicationLocked(thread, callingPid);
- ... ...
- }
-
- private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
- ProcessRecord app;
- ... ...
- if (mStackSupervisor.attachApplicationLocked(app)) {
- ... ...
- }
-
- boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
- ... ...
- ActivityRecord hr = stack.topRunningActivityLocked(null);
- if (hr != null) {
- if (hr.app == null && app.uid == hr.info.applicationInfo.uid
- && processName.equals(hr.processName)) {
- try {
- if (realStartActivityLocked(hr, app, true, true)) {
- ... ...
- }
首先取出栈顶的activity,也就是要要启动的新activity,然后调用realStartActivityLocked()。
- final boolean realStartActivityLocked(ActivityRecord r,
- ProcessRecord app, boolean andResume, boolean checkConfig) {
- ... ...
- app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
- System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
- r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
- r.icicle, r.persistentState, results, newIntents, !andResume,
- mService.isNextTransitionForward(), profilerInfo);
- ... ...
- }
和之前的pause activity一样,这里也是通过IApplicationThread代理调用到app端的ActivityThread,只不过这里是新创建的app进程的ActivityThread。
- public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
- String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
- PersistableBundle persistentState, List pendingResults,
- List pendingNewIntents, boolean notResumed, boolean isForward,
- ProfilerInfo profilerInfo) {
- ActivityClientRecord r = new ActivityClientRecord();
- ... ...
- sendMessage(H.LAUNCH_ACTIVITY, r);
- }
这里创建了我们之前遇到过的ActivityClientRecord对象,实际上可以理解为对端ActivityRecord的一个本地镜像。然后发送LAUNCH_ACTIVITY的消息启动新的activity。
- public void handleMessage(Message msg) {
- ... ...
- switch (msg.what) {
- case LAUNCH_ACTIVITY: {
- final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
- ... ...
- handleLaunchActivity(r, null);
- ... ...
- }
-
- private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
- ... ...
- Activity a = performLaunchActivity(r, customIntent);
- ... ...
- }
-
- private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
- ... ...
- Activity activity = null;
- try {
- java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
- activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
- StrictMode.incrementExpectedActivityCount(activity.getClass());
- ... ...
- }
- ... ...
- Application app = r.packageInfo.makeApplication(false, mInstrumentation);
- ... ...
- if (activity != null) {
- Context appContext = createBaseContextForActivity(r, activity);
- CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
- activity.attach(appContext, this, getInstrumentation(), r.token,
- r.ident, app, r.intent, r.activityInfo, title, r.parent,
- r.embeddedID, r.lastNonConfigurationInstances, config,
- r.referrer, r.voiceInteractor);
- ... ...
- if (r.isPersistable()) {
- mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
- } else {
- mInstrumentation.callActivityOnCreate(activity, r.state);
- }
- ... ...
- }
- ... ...
- mActivities.put(r.token, r);
- ... ...
- }
这里执行了3个关键步骤:
- 通过class loader加载activity类,并创建新的activity对象
- 创建Application对象(即Applicaiton Context)
- 创建activity的上下文对象,调用onCreate()方法
中间还有一步调用activity的attach()方法,会创建PhoneWindow对象并与WindowManagerService建立联系,后面会专门写一篇文章研究这部分内容。
至此,整个应用程序的启动流程就基本完成了。