1、Activity应用启动的几个阶段
- 准备阶段:做进程启动前的准备工作。
- 进程启动阶段:通过Zygote启动进程。(当应用已经启动时,此步骤略)
- Activity启动阶段:在新的进程里,启动Activity。
2. 准备阶段
2.1 Launcher启动准备
《Android入门 -系统启动简介》已经分析了,Launcher的启动是通过ActivityManagerService.startHomeActivityLocked启动的:- startHomeActivityLocked:
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java://获取主屏幕Intent Intent getHomeIntent() { Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null); intent.setComponent(mTopComponent); if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { intent.addCategory(Intent.CATEGORY_HOME); } return intent; } boolean startHomeActivityLocked(int userId) { ... // 获取主屏幕的Intent Intent intent = getHomeIntent(); // 获取主屏幕的Activity信息(如:包名,Activity名,应用信息,进程名等) ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId); if (aInfo != null) { // 设置主屏幕Intent的组件信息 intent.setComponent(new ComponentName( aInfo.applicationInfo.packageName, aInfo.name)); // Don't do this if the home app is currently being // instrumented. aInfo = new ActivityInfo(aInfo); aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId); // 获取主屏幕应用的进程信息 ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true); if (app == null || app.instrumentationClass == null) { // 假如主屏幕应用进程未启动,则启动 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); mStackSupervisor.startHomeActivity(intent, aInfo); } } return true; }
- startActivityLocked:
frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java:void startHomeActivity(Intent intent, ActivityInfo aInfo) { moveHomeToTop(); startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0, null, false, null); }
2.2、一般应用启动准备流程
这里,我们先创建一个HelloAndroid的应用,再创建一个TestCallApp的应用,尝试在TestCallApp里,启动HelloAndroid应用。2.2.1、创建HelloAndroid应用
在Eclipse里,NewProject->Android ApplicationProject,取名:HelloAndroid,package名为:com.helloandroid。按向导一直Next,最后点击finish。
打开AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.helloandroid" android:versioncode="1" android:versionname="1.0">
<uses-sdk android:minsdkversion="19" android:targetsdkversion="19">
<application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme">
<activity android:name="com.helloandroid.MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN">
<action android:name="com.helloandroid.HELLO">
<category android:name="android.intent.category.DEFAULT">
<category android:name="android.intent.category.LAUNCHER">
</category></category></action></action></intent-filter>
</activity>
</application>
</uses-sdk></manifest>
intent-filter下面已经有一个名为“android.intent.action.MAIN”的action和一个名为“android.intent.category.LAUNCHER”的category,这是用于在Launcher里点击用户图标来启动应用的。我们在intent-filter下新增一个名为“com.helloandroid.HELLO”的action和一个名为“android.intent.category.DEFAULT”的category,这样做是为了方便其他程序调用。本章暂不详细讨论Intent。
点击Run,安装并运行HelloAndroid应用。
2.2.2、创建TestCallApp应用
创建应用的方法同上,名称用:TestCallApp,包名为:com.testcallapp。打开fragment_main.xml,转至GraphicalLayout,拖一个Button放到界面上,ID为call_button。
转至MainActivity.java:
...
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// 加入下面代码
Button b = (Button) rootView.findViewById(R.id.call_button);
if (b != null)
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.helloandroid.HELLO");
startActivity(intent);
}
});
return rootView;
}
}
...
上面是在Activity里内嵌了一个Fragment碎片,如果没用Fragment,可以在Activity.OnCreate里写上面的代码。
点击Run,运行并安装此程序。点击”Call“按钮,即可启动HelloAndroid应用。
此案例说明了如何从一个应用里启动另一个应用,也是用Intent,通过Activity.startActivity()函数来调用。
2.3、流程图
在上图中我们可以知道,Home应用启动流程是在1.3.1.1.2.1:startActivityLocket步骤开始的,后面的流程与一般应用的启动流程相同。
2.4 关键流程解析
2.4.1 Binder通信
...
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
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, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
...
流程走到这里,突然看不到源码了,因为IActivityManager是一个接口,通过调用IActivityManager.startActivity函数,来启动Activity。那么,IActivityManager的实现类在哪?先来看看ActivityManagerNative.getDefault()干了什么。
frameworks/base/core/java/android/app/ActivityManagerNative.java
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
...
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);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
ActivityManagerNative.gDefault是一个私有的单例模式运行的成员变量,保存当前默认的IActivityManager,从create代码可以看出,gDefault是"activity"服务的一个通信代理,即:ActivityManagerProxy,通过IBinder与ActivityManagerService通信,进入到ActivityManagerService.startActivityLocked。
2.4.2 ActivityStatck.startActivityLocked
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
if (taskForIdLocked(taskId) == null || newTask) {
// 如果是新任务,则将任务插入到任务列表顶端
// Last activity in task had been removed or ActivityManagerService is reusing task.
// Insert or replace.
// Might not even be in.
insertTaskAtTop(rTask);
mWindowManager.moveTaskToTop(taskId);
}
TaskRecord task = null;
if (!newTask) {
...
}
...
task = r.task;
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
// 将Activity插到任务的Activities顶端,一个任务可以有多个Activities
task.addActivityToTop(r);
// 标记Activity已经在历史记录中
r.putInHistory();
r.frontOfTask = newTask;
if (!isHomeStack() || numActivities() > 0) {
// 非home下的窗口处理,略
...
} else {
// home下的窗口处理,涉及锁屏等,略
...
}
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
if (doResume) {
// 恢复或启动顶层的Activity,本函数之前已经将Activity置入顶层
mStackSupervisor.resumeTopActivitiesLocked();
}
}
本函数先将Activity插入到Activities的顶端,再调用resumeTopActivitiesLocked函数,走到ActivityStack.resumtTopActivityLocked。
2.4.3 ActivityStackSupervisor.resumeTopActivitiesLocked:
frameworks/base/services/java/com/android/server/am/ActivityStack.javafinal boolean resumeTopActivityLocked(ActivityRecord prev) {
return resumeTopActivityLocked(prev, null);
}
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
// 找到顶层的ActivityRecord
// Find the first activity that is not finishing.
ActivityRecord next = topRunningActivityLocked(null);
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
if (next == null) {
// 此处启动Launcher,在上一篇文章有描述,不过,经过一翻流转,最终还是会回到本函数,但此时next不是null了。Android源码,哎。。。
...
}
...
if (next.app != null && next.app.thread != null) {
// 应用已经启动情况,有可能会重启动应用,此处不分析
...
} else {
...
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
上面的函数逻辑非常复杂,有许多的return语句,这些return之后,经过一翻流转有可能又进入此函数,进入另一个判断分支。本文不详细分析Activity的各种复杂管理,只讨论如何启动,所以,略去了这许多代码。
2.4.4 ActivityStackSupervisor.startSpecificActivityLocked:
frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.javavoid 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) {
// 如果进程已经运行。。。当然,在一个应用内启动自己的Activity,肯定会进入此段代码
try {
// 直接启动Activity,
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
//启动进程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
如果应用已经运行,则直接进入Activity启动阶段,否则,进入进程启动阶段。
说明:如何判断应用是否已经运行,这个在前面的源代码并未详细分析,本文也不准备详细分析,今后如果有项目的需要,再来继续深入研究,目前,了解到这么多足够了,因为如果是单实例应用,分析的必要性不大,而多实例(MULTI)应用并不多见。
3 进程启动阶段
4 Activity启动阶段
4.1 流程图
4.2 关键流程解析
4.2.1 发送H.LAUNCH_ACTICITY消息
boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
boolean didSomething = false;
final String processName = app.processName;
// 找到app对应的ActivityRecord,并调用realStartActivityLocked启动Activity。
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
if (!isFrontStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked(null);
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (headless) {
Slog.e(TAG, "Starting activities not supported on headless device: "
+ hr);
} else if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0);
}
return didSomething;
}
...
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
...
r.app = app;
app.waitingToKill = null;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
...
final ActivityStack stack = r.task.stack;
try {
if (app.thread == null) {
throw new RemoteException();
}
...
// 启动Activity
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new Configuration(mService.mConfiguration), r.compat,
app.repProcState, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
...
} catch (RemoteException e) {
...
throw e;
}
...
return true;
}
在《Android 进阶 - 进程启动分析》一文,已经说明,app.thread是一个IApplicationThread的Binder远程接口,可以通过app.thread,经由Binder进入Activity的thread服务端对象,即ApplicationThread类的实例,所以,app.thread是ActivityManagerService反调Activity应用的桥梁。app.thread.scheduleLaunchActivity经由Binder,进入到ApplicationThread.scheduleLaunchActivity函数中。
frameworks/base/core/java/android/app/ActivityThread.java
public class ActivityThread{
// mH是一个H类实例
final H mH = new H();
...
// H类继承自android.os.Handler类。
private class H extends Handler {
}
...
class ApplicationThread{
...
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
int procState, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profileFile = profileName;
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
....
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
...
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发送消息。
mH.sendMessage(msg);
}
}
}
然后,通过Looper机制,发送H.LAUNCH_ACTICITY消息。
frameworks/base/core/java/android/os/Handler.java
public Handler{
...
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
...
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
...
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
...
// 通过前面的调用,最终进入本函数,执行消息入队
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
// 将消息的target,指向自己,这样在Looper.loop中可以调用msg.target.dispatchMessage来回调本Handle的消息处理
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
}
本函数流程比较简单,创建一个ActivityClientRecord,然后,发送LAUNCH_ACTIVITY消息,启动一个Activity。消息通过mH发送,走到android.os.Handler.enqueueMessage函数,完成消息的入队,具体见上面的源代码注释。有关Looper消息的内容,参见《Android 进阶 - Looper进程内通信》一文。
上面的代码,其实只是将msg放入到mQueue队列中。尽管这里用的mQueue队列,但并不是异步处理,因为此段代码的在main线程中执行。后面的Looper.loop()函数会处理这个消息的。
4.2.2 处理H.LAUNCH_ACTIVITY
前面已经将H.LAUNCH_ACTICITY消息发送给Looper.mainLooper,接下来,就是处理消息了。在ActivityThread.main()函数中,调用attach函数()之后,会执行Looper.loop(),进入消息循环,处理消息。由于之前的消息是通过mH发送,所以,消息的处理,最终会进入H.handleMessage中,这在Looper进程内通讯一文中有详细描述。frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread {
...
final H mH = new H();
...
private class H extends Handler {
...
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
// 处理H.LAUNCH_ACTIVITY消息
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
...
}
}
...
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
...
} else {
...
}
}
...
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
...
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
// 创建新的Activity实例
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
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) {
// 为Activity创建上下文
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与上下文连接
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
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;
// 发送Activity.OnCreate事件,在这里可调用用户定义的事件。
mInstrumentation.callActivityOnCreate(activity, r.state);
...
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
...
}