之前在Mac环境下搭建了Android源码,接下来会在简书记录阅读一些经典场景的源码过程, 本文主要是在阅读启动Activity源码过程中做的一些记录, 其中主要的思路是参考罗老师的文章:Android应用程序启动过程源代码分析
几个重要概念
在看Activity启动源码之前,先看几个概念, 这几个是理解Activity启动流程的重要概念:
ActivityManagerService: AMS,服务端的类, 管理着Activity相关的行为
ApplicationThread:实现了IApplicationThread接口,这个接口的说明是
/**
This is given to the activity manager by an application when it starts up, for the activity manager to tell the application about things it needs to do
**/
它是用来实现ActivityManagerService和ActivityThread之间的交互
ActivityThread:
/**
* This manages the execution of the main thread in an
* application process, scheduling and executing activities,
* broadcasts, and other operations on it as the activity
* manager requests.
*/
ActivityThread是App主线程(UI线程)管理者,并且作为调度和执行Activity, broadcast的角色。所以,Activity相关的操作,都是由ActivityThread来调度的。
对于每一个应用程序来说,都有一个ActivityThread来表示应用程序的主进程,而每一个ActivityThread都包含有一个ApplicationThread实例,它是一个Binder对象,负责和其它进程进行通信。
- instrumentation
这里的mInstrumentation是ActivityThread类的成员变量,它的类型是Intrumentation,定义在frameworks/base/core/java/android/app/Instrumentation.java文件中,它用来监控应用程序和系统的交互。
源码
说完几个基础概念,下面我们来看startActivity(Intent)的源码:
-
startActivity函数也是调用了startActivityResult, 然后跟进去可以看到如下代码:
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);
这里就出现了我们上面提到的Instrumentation对象,它是监控应用程序和系统交互的类。执行execStartActivity方法,这里有两个参数重点看一下:
mMainThread.getApplicationThread(): ApplicationThread对象,它是用来与服务端ActivityManagerServer交互的;
mToken: IBinder对象; -
下面是execStartActivity的源代码:
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) { throw new RuntimeException("Failure from system", e); } return null; }
这里我省略了中间一段,就看核心的ActivityManagerNative.getDefault().startActivity这个函数,先看看getDefault获取了一个什么对象
-
下面是getDefault的实现:
/*** Retrieve the system's default/global activity manager. */ static public IActivityManager getDefault() { return gDefault.get(); } private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { //通过ServiceManager获取对应Service IBinder b = ServiceManager.getService("activity"); if (false) { Log.v("ActivityManager", "default service binder = " + b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service = " + am); } return am; } };
上述代码我们看到一段熟悉的Binder机制代码, 就是ServiceManager.getService("activity"), 大概理解Binder机制就会知道,Binder是C/S架构,而Client客户端就是通过ServiceManager.getService的方式获取服务端代理对象(所以说是代理对象,因为真正的服务端在另外一个进程中)。
-
再回到刚刚ActivityManagerNative.getDefault().startActivity,getDefault是IActivityManager接口, 实例对象是ActivityManagerProxy,下面看看这个ActivityManagerProxy代码:
这里就是经典的Binder的模式, 这里的mRemote就是上面第3步代码中获取的Service对象 -
第4步通过Binder机制(后面会再详细看看Binder机制, 简单说就是客户端方法映射到服务端的方法),所以这里就进入了服务端(另外一个进程)ActivityManagerService的startActivity函数:
这里主要是调用了ActivityStackSupervisor类的startActivityMayWait方法, 下面会重点看一下ActivityStackSupervisor这个类的处理: -
startActivityMayWait(), 里面主要是对Intent做了解析,将要启动的Activity的信息保存在ActivityInfo(变量对应的是aInfo)中, 然后调用startActivityLocked方法;
-
startActivityLocked: 这里又解析了一些信息,例如调用者callApp等,然后生成一个ActivityRecord对象
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, this, container, options); err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask);
-
startActivityUncheckedLocked: 这个函数大约有六百多行代码,这个函数主要处理了Task相关的逻辑, 在AndroidManifest或者代码中, 我们可以定义Activity的4中启动模式: standard, singleTop, singleTask, singleInstance。这里就是判断了具体的启动模式,并根据当前Activity栈的情况,作出不同的处理。
最终,走到一个基本的启动模式函数:targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options) - startActivityLocked在ActivityStack文件中,这里继续对Task相关的逻辑做处理,不做深入的分析了, 直接看接下来的处理: resumeTopActivitiesLocked
- resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options); 它的其中一个参数prev是在stack中的上一个activity, 那么这个函数要做的是对上一个activity做一些事情了,下面看具体的代码:
其中的注释说的很明白: 要启动top activity, 我们必须将目前正在运行的activity置于pause的状态。// We need to start pausing the current activity so the top one // can be resumed... boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0; boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause); if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause); }
- 下面又来到一个比较关键的节点:“将当前activity置于pause状态”, 代码如下:
可以看到,最核心的是调用了prev.app.thread.schedulePauseActivity, 其中app是ProcessRecord对象,是当前正在前台运行的应用相关信息; thread是IApplicationThread对象,文中一开始的时候提到的ApplicationThread实现了这个接口,是应用进程和ActivityManagerService服务进程间通信的桥梁。if (prev.app != null && prev.app.thread != null) { 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); prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, userLeaving, prev.configChangeFlags, dontWait); }
下面要执行的就是进程间的通信了,这里是第二次执行Binder进程间通信了(第一次是第5步的时候, 应用进程作为客户端client,通知服务端AMS调用startActivity),这一次,则正好相反,是AMS进程通知应用进程执行pause activity操作。
------------一条分割线-------------
这里再详细看看为什么thread.schedulePauseActivity可以完成一次Binder跨进程的调用,在一开始接触Binder的时候,都是client调用service的方法, 而service由ServiceManager对象管理,所以,client要调用service的时候,可以通过ServiceManager.getService("activity")这样的方法获取,现在是service调用client,那么service又是怎么知道我要调用哪个client呢?
那要看看thread这个对象是怎么生成的? 通过一层层函数调用发现thread对象传递的流程如下:
最开始, 当application启动的时候,ActivityThread的main函数作为应用程序的入口, 有如下这段代码:
这里就通过Binder机制,将mAppThread对象,也就是我们一直提到ApplicationThread传递给ActivityManagerService, 而在service中的处理:thread.attach(false); private void attach(boolean system) { ... final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } ... }
上面这段代码, 很好的解释了, 我们上面看到的prev.app.thread对象, 就是当应用启动的时候从ActivityThread传递过来的ApplicationThread对象。所以调了thread.schedulePauseActivity, 就可以实现service与当前应用进程的通信;public void handleMessage(Message msg) { switch (msg.what) { case ATTACH_APPLICATION_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IApplicationThread app = ApplicationThreadNative.asInterface( data.readStrongBinder()); if (app != null) { attachApplication(app); } reply.writeNoException(); return true; } } } Override public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } } private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { app.makeActive(thread, mProcessStats); } public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) { thread = _thread; }
------------又是一条分割线------------- -
这里,我们又回到了应用进程, 执行的是ApplicationThread对象的schedulePauseActivity方法:
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); }
因为ApplicationThread是ActivityThread的内部类,sendMessage函数是ActivityThread的实现, 如下:
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj); Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; if (async) { msg.setAsynchronous(true); } mH.sendMessage(msg); }
可以看到,这里是一个Handler发送消息的机制,ActivityThread的成员变量mH处理了来自ApplicationThread的PAUSEACTIVITY消息。至于这里为什么要用Handler机制呢?因为ApplicationThread作为和服务端交互的桥梁,它是单独挂起一个线程在接收服务端的消息的, 而下面我们要操作的是在主线程(UI线程)做PAUSEACTIVITY的处理, 所以这里就需要一个Handler把消息传递给主线程去执行相应操作。看下面的代码:
//handler处理pause消息 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; //ActivityThread处理pauseActivity private void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) { ActivityClientRecord r = mActivities.get(token); if (r != null) { //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); if (userLeaving) { performUserLeavingActivity(r); } r.activity.mConfigChangeFlags |= configChanges; performPauseActivity(token, finished, r.isPreHoneycomb()); // Make sure any pending writes are now committed. if (r.isPreHoneycomb()) { QueuedWork.waitToFinish(); } // Tell the activity manager we have paused. if (!dontReport) { try { //通知服务端 ActivityManagerNative.getDefault().activityPaused(token); } catch (RemoteException ex) { } } mSomeActivitiesChanged = true; } } //由activity管理者来执行pause操作 final Bundle performPauseActivity(ActivityClientRecord r, boolean finished, boolean saveState) { mInstrumentation.callActivityOnPause(r.activity); } //Activity 文件中的pause处理 final void performPause() { mDoReportFullyDrawn = false; mFragments.dispatchPause(); mCalled = false; onPause(); mResumed = false; if (!mCalled && getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.GINGERBREAD) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + " did not call through to super.onPause()"); } mResumed = false; }
可以看到,在最后Activity中的performPause() 函数中,调用了我们熟悉的生命周期函数onPause(), 到这里,就完成了服务端的PAUSEACTIVITY操作, 然后再ActivityThread中,又通知了服务端完成pauseActivity操作: ActivityManagerNative.getDefault().activityPaused(token);
-
下面又通过Binder机制回到Service端的代码, ActivityManagerService的activityPaused():
Override public final void activityPaused(IBinder token) { final long origId = Binder.clearCallingIdentity(); synchronized(this) { ActivityStack stack = ActivityRecord.getStackLocked(token); if (stack != null) { stack.activityPausedLocked(token, false); } } Binder.restoreCallingIdentity(origId); } //ActivityStack.java final void activityPausedLocked(IBinder token, boolean timeout) { final ActivityRecord r = isInStackLocked(token); if (r != null) { mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); if (mPausingActivity == r) { completePauseLocked(true); } } }
接下来继续执行resumeActivity的操作, 这里我省略了一些ActivityStack文件中的函数的跳转,直接看下面关键的节点函数:
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.task.stack.setLaunchTime(r); if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } // If a dead object exception was thrown -- fall through to // restart the application. } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }
这里的判断if (app != null && app.thread != null)中的两个变量在前面已经介绍过, 如果应用程序已经启动,在内部进行跳转的时候,这两个变量都是不为空的, 那么,我们就进入了realStartActivityLocked这个函数, 这个函数则会执行如下代码:
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
这段代码和上面app.thread.schedulePauseActivity非常相似, 这里也是通过Binder机制,又从服务端通知客户端ApplicationThread去执行scheduleLaunchActivity:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { Activity a = performLaunchActivity(r, customIntent); } private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")"); ActivityInfo aInfo = r.activityInfo; if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); } ComponentName component = r.intent.getComponent(); if (component == null) { component = r.intent.resolveActivity( mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if (r.activityInfo.targetActivity != null) { component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); } Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(); if (r.state != null) { r.state.setClassLoader(cl); } } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to instantiate activity " + component + ": " + e.toString(), e); } } try { Application app = r.packageInfo.makeApplication(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV) Slog.v( TAG, r + ": app=" + app + ", appName=" + app.getPackageName() + ", pkg=" + r.packageInfo.getPackageName() + ", comp=" + r.intent.getComponent().toShortString() + ", dir=" + r.packageInfo.getAppDir()); if (activity != null) { Context appContext = createBaseContextForActivity(r, activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor); if (customIntent != null) { activity.mIntent = customIntent; } r.lastNonConfigurationInstances = null; activity.mStartedActivity = false; int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); } activity.mCalled = false; if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } r.activity = activity; r.stopped = true; if (!r.activity.mFinished) { activity.performStart(); r.stopped = false; } if (!r.activity.mFinished) { if (r.isPersistable()) { if (r.state != null || r.persistentState != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState); } } else if (r.state != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } } if (!r.activity.mFinished) { activity.mCalled = false; if (r.isPersistable()) { mInstrumentation.callActivityOnPostCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnPostCreate(activity, r.state); } if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onPostCreate()"); } } } r.paused = true; mActivities.put(r.token, r); } } }
performLaunchActivity通过ClassLoader类加载机制生成Activity对象,然后通过Instrumentation去执行生命周期的函数, 同时还设置了主题等其他初始化操作。
到这里, 就基本将Activity启动流程走了一遍, 其中重点描述了几次Client与Service交互的操作,对于一些函数内部的实现没有深入分析,仅仅是走了一遍流程,在此做一些记录。