最近由于工作需要,需要深入了解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 {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
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<IActivityManager> gDefault = new Singleton<IActivityManager>() {
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()方法。
// Activity manager runs the show.
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
public <T extends SystemService> T startService(Class<T> serviceClass) {
... ...
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
... ...
// Register it
mServices.add(service);
// Start it
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() {
... ...
// Set up the Application instance for the system process and get started.
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();
... ...
// Should this be considered a new task?
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 /* toTop */),
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) {
... ...
// Find the first activity that is not finishing.
final ActivityRecord next = topRunningActivityLocked(null);
... ...
// We need to start pausing the current activity so the top one
// can be resumed...
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());
... ...
// Tell the activity manager we have paused.
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;
... ... //初始化ProcessRecord的一些字段
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<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
ProfilerInfo profilerInfo) {
ActivityClientRecord r = new ActivityClientRecord();
... ... //初始化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建立联系,后面会专门写一篇文章研究这部分内容。
至此,整个应用程序的启动流程就基本完成了。