之前在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对象,负责和其它进程进行通信。
说完几个基础概念,下面我们来看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 gDefault = new Singleton() {
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)
// 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);
}
其中的注释说的很明白: 要启动top activity, 我们必须将目前正在运行的activity置于pause的状态。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);
}
可以看到,最核心的是调用了prev.app.thread.schedulePauseActivity, 其中app是ProcessRecord对象,是当前正在前台运行的应用相关信息; thread是IApplicationThread对象,文中一开始的时候提到的ApplicationThread实现了这个接口,是应用进程和ActivityManagerService服务进程间通信的桥梁。thread.attach(false);
private void attach(boolean system) {
...
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
}
...
}
这里就通过Binder机制,将mAppThread对象,也就是我们一直提到ApplicationThread传递给ActivityManagerService, 而在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;
}
上面这段代码, 很好的解释了, 我们上面看到的prev.app.thread对象, 就是当应用启动的时候从ActivityThread传递过来的ApplicationThread对象。所以调了thread.schedulePauseActivity, 就可以实现service与当前应用进程的通信;这里,我们又回到了应用进程, 执行的是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交互的操作,对于一些函数内部的实现没有深入分析,仅仅是走了一遍流程,在此做一些记录。