Android App 启动流程
在刚开始接触Android的时候就尝试着去看ActivityThread
,希望能明白App的启动流程。毋庸置疑,当时是以失败而告终的。现在又卷土重来,重新尝试着去看,发现以前困惑的地方都豁然开朗了。当然,也是阅读了一些优秀的文章的。
那么为什么我在这里又写一篇呢?是他们写的不好么,并不是的,而是希望能把自己遇到的一些困惑的地方和自己的理解与大家一起分享下,希望能帮到大家。
下面是我参考的博客,没错,就是老罗的。
http://blog.csdn.net/luoshengyang/article/details/6689748
写的非常详细,但是自己没有去看过,跟踪过源码跳转,是很难看懂的。所以不管是看上面的博客,还是看我这篇文章,你至少要先自己一步步跟踪过代码。
注意:Android源码 2.3.1
下面开始分享:
前言
- 手机整个桌面其实也是一个应用程序,叫Launcher,继承Activity
- 点击Launcher下的桌面图标,触发onClick事件,才是我们要看的第一个入口
- 每个应用程序有自己的ActivityThread,Launcher也是
- ActivityManagerProxy与ActivityManagerService是一对Binder
- ApplicationThread与ActivityThreadProxy是一对Binder
- ActivityManagerProxy和ApplicationThread是应用程序进程中使用
- ApplicationThreadProxy是在ActivityManagerService中使用
- ActivityManagerService只存在一个,在系统启动的时候,就已创建
基本上看到这里还没晕的话,已经很强了。下面继续。
我所在意的几件事
ActivityThread是什么时候创建的
既然说了每个应用程序都有自己的一个ActivityThread,那么我最关心的肯定是这个ActivityThread到底是什么时候创建的。如果你通过跟踪代码一步步跟入,其实是很难跟到这一步的,因为里面有太多的if判断,分支多,代码长。
我指下位置:
framework/base/services/java/com/android/server/am/ActivityManagerService.java
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
...
int pid = Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName : null, uid, uid,
gids, debugFlags, null);
...
}
我简单的说下流程。
一开始所在的进程是Launcher所在的进程,Launcher有自己的ActivityThread,也有就是说有自己的ApplicationThread,ActivityManagerProxy,ApplicationThreadProxy来与ActivityManagerService进行交互。当我们在Launcher中点击一个App图标,Launcher就监测到onClick事件,然后与ActivityManagerService进行交互后(这里交互有几个步骤,我这不具体细说,可以看看我上面推荐的博客),告诉ActivityManagerService可以启动这个App的MainActivity了,然后一判断,发现这个MainActivity还没有自己的ActivityThread然后就启动。
步骤很多,但是我前面也说过,我这篇文章不会写太大篇幅贴代码,然后去分析,因为老罗的blog确实很详细了,我主要是想把我当时遇到的问题给大家分享一下,我当时就是一直找不到ActivityThread他到底是在哪里启动的。
ActivityManagerProxy,ApplicationThread,ApplicationThreadProxy哪里创建
前面也简单的介绍了,我们的App正是通过这3个类与ActivityManagerService进行交互的,把他们搞懂的,差不多已经对整个流程理解了一半了,确实是这样,第一次阅读这个源码的时候,我就是很难理解他们的关系,所以有些地方一直无法走通,导致半途而废。所以,为了弄懂这3个类,首先第一步我们要了解这3个类分别是在哪里创建的,对我们理解也会有一些帮助。
ApplicationThread创建:
framework/base/core/java/android/app/ActivityThread.java
public final class ActivityThread {
...
final ApplicationThread mAppThread = new ApplicationThread();
...
public static final void main(String[] args) {
...
ActivityThread thread = new ActivityThread();
}
}
启动ActivityTread,先进入main函数,然后创建ActivityThread
,ApplicationThread就会被创建。
ActivityManagerProxy创建:
framework/base/core/java/android/app/ActivityThread.java
public final class ActivityThread {
private final void attach(boolean system) {
...
IActivityManager mgr = ActivityManagerNative.getDefault();
...
}
public static final void main(String[] args) {
...
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
}
}
framework/base/core/java/android/app/ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
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);
}
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault()
{
if (gDefault != null) {
//if (Config.LOGV) Log.v(
// "ActivityManager", "returning cur default = " + gDefault);
return gDefault;
}
IBinder b = ServiceManager.getService("activity");
if (Config.LOGV) Log.v(
"ActivityManager", "default service binder = " + b);
gDefault = asInterface(b);
if (Config.LOGV) Log.v(
"ActivityManager", "default service = " + gDefault);
return gDefault;
}
...
...
}
创建好ActivityThread对象后会执行attach方法,然后在里面调用ActivityManagerNative.getDefault()方法,
ActivityManagerProxy是ActivityManagerNative的子类,最终会在asInterface方法中new一个ActivityManagerProxy。值得关注的是,在new ActivityManagerProxy的时候传入一个Binder。我们再看getDefault方法,其实这个Binder就是 ServiceManager.getService("activity"),也就是ActivityManagerService。
ApplicationThreadProxy创建:
framework/base/core/java/android/app/ActivityThread.java
public final class ActivityThread {
private final void attach(boolean system) {
...
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
...
}
public static final void main(String[] args) {
...
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
}
}
framework/base/core/java/android/app/ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
...
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IApplicationThread app = ApplicationThreadNative.asInterface(
data.readStrongBinder());
if (app != null) {
attachApplication(app);
}
reply.writeNoException();
return true;
}
...
...
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app.asBinder());
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
...
}
framework/base/core/java/android/app/ApplicationThreadNative.java
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread {
/**
* Cast a Binder object into an application thread interface, generating
* a proxy if needed.
*/
static public IApplicationThread asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IApplicationThread in =
(IApplicationThread)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ApplicationThreadProxy(obj);
}
...
...
}
ApplicationThreadProxy的创建是最复杂的,一共涉及到了3个文件,其中最关键的还是在ActivityManagerNative
中的调用。已经设计到了跨进程通信,我在后面再详细描述。
上面3个类的作用
其实在前言
中我已经对他们的关系做好简单的描述,下面我们再看下。
- ActivityManagerProxy与ActivityManagerService是一对Binder
- ApplicationThread与ActivityThreadProxy是一对Binder
- ActivityManagerProxy和ApplicationThread是应用程序进程中使用
- ApplicationThreadProxy是在ActivityManagerService中使用
一对Binder的作用是,这2个Binder分别处在不同的进程,如果要进行通信,就要write,read等方法,也就是Binder机制,这个机制在这里我不过多介绍,因为对整个流程来说,你只要知道,我们跨进程是用它来实现的就可以了,并不需要去了解实现的细节。
我这里可能还说的不够明确,那么我再明确一下。
ActivityManagerService与我们的App处在不同的进程。这意味着,ActivityManagerService要给我们App发送一个消息只能通过ApplicationThreadProxy,然后我们在ApplicationThread这个对象中读取到ApplicationThreadProxy通过Binder机制传过来的数据,然后进行处理。同理,我们App要与另外一个进程中的ActivityManagerService只能通过ActivityManagerProxy来实现,因为他们是一对Binder,在创建的时候就已经进行了绑定。
这3个类到底是怎么与ActivityManagerService交互的,来个demo
交互流程很复杂很多,大家都知道Activity
有很多生命周期函数,其实都是这几者之间交互的时候发生的,所以我不过多介绍,带大家走一个来回的交互,还是从ActivityThread
这个入口开始。
framework/base/core/java/android/app/ActivityThread.java
public final class ActivityThread {
private final void attach(boolean system) {
...
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
...
}
public static final void main(String[] args) {
...
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
}
}
framework/base/core/java/android/app/ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
...
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IApplicationThread app = ApplicationThreadNative.asInterface(
data.readStrongBinder());
if (app != null) {
attachApplication(app);
}
reply.writeNoException();
return true;
}
...
...
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app.asBinder());
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
...
class ActivityManagerProxy implements IActivityManager
{
public ActivityManagerProxy(IBinder remote)
{
mRemote = remote;
}
}
}
这里代码是关键,我们在ActivityThread中调用attachApplication,mRemote其实就是就是在创建ActivityManagerProxy传入的Binder,前面也介绍了,其实也就是ActivityManagerService。因为ActivityManagerService是继承ActivityManagerNative的,ActivityManagerNative继承了Binder.
在attachApplication方法中调用mRemote.transact(),其实是调用了Binder的transact方法。
framework/base/core/java/android/os/Binder.java
...
/**
* Default implementation rewinds the parcels and calls onTransact. On
* the remote side, transact calls into the binder to do the IPC.
*/
public final boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (Config.LOGV) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
...
最终触发了onTransact
方法。我们这里首先要明白调用transact的是ActivityManagerService。所以,当我们运行到这里的时候其实已经切换到了ActivityManagerService所在的进程。
然后我们再进入下一步。因为在ActivityManagerNative中,对Binder的onTransact重写,所以我们最终触发的是在ActivityManagerNative中的onTransact方法。
framework/base/core/java/android/app/ActivityManagerNative.java
...
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IApplicationThread app = ApplicationThreadNative.asInterface(
data.readStrongBinder());
if (app != null) {
attachApplication(app);
}
reply.writeNoException();
return true;
}
...
}
}
...
在前面调用transact方法时传入了code,ATTACH_APPLICATION_TRANSACTION
。其实在前面介绍那3个重要的类中的ApplicationThreadProxy的创建过程的时候,也是这里的代码,没错,这里是非常重要的一步,因为在这里创建了ApplicationThreadProxy这个类,有了这个类,ActivityManagerService才能与我们的App进行交互。
我们其实可以回顾下,ActivityManagerProxy的创建,new的时候是传入了ActivityManagerService的,也就是另一个Binder。这样才能把2者绑定,相互读写数据。同理,ApplicationThreadProxy创建的时候,也应该是传入一个Binder,既然前面说了ApplicationThreadProxy与ApplicationThread是一对,那么就应该传入ApplicationThread。data.readStrongBinder() 这里读取到的,也就是我们App进程通过Binder机制传过来的,其实就是我们需要的ApplicationThread。
接下来,也就是最关键的一步,其实也是我在第一次阅读源码的时候卡住的时候。
调用attachApplication方法。一般情况下,我们就直接搜索这个方法,发现在当前这个类ActivityManagerNative下就有这个方法,就是我们刚才已经调用过的方法。
framework/base/core/java/android/app/ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
...
...
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app.asBinder());
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
...
哎,这里好奇怪,我已经通过Binder机制把数据传给ActivityManagerService了,怎么又重复调用这个attachApplication方法,又要传一遍数据么,感觉无限死循环了呀。
前面我已经说了,当前其实是在ActivityManagerService下了,所以应该调用的是ActivityManagerService下的
attachApplication方法,虽然ActivityManagerService是ActivityManagerNative的子类,但是他对attachApplication这个方法进行了重写。
framework/base/services/java/com/android/server/am/ActivityManagerService.java
```java
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...
thread.bindApplication(processName, app.instrumentationInfo != null
? app.instrumentationInfo : app.info, providers,
app.instrumentationClass, app.instrumentationProfileFile,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
isRestrictedBackupMode || !normalMode,
mConfiguration, getCommonServicesLocked());
...
}
...
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
...
走到这一步了,基本上接下来就差不多了。
thread其实就是ApplicationThreadProxy,这里就是ActivityManagerService通知我们App绑定Application。
首先我们要搞清楚,我们调用的是ApplicationThreadProxy的bindApplication。因为我们App端的ApplicationThread也有bindApplication这个方法。
所以这里有个很重要的提示,一定要搞清楚这2对Binder到底是在调用谁,因为他们里面的方法都是类似的,你一个搞混了,接下来是走不下去的。
framework/base/core/java/android/ApplicationThreadNative.java
...
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case BIND_APPLICATION_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
String packageName = data.readString();
ApplicationInfo info =
ApplicationInfo.CREATOR.createFromParcel(data);
List<ProviderInfo> providers =
data.createTypedArrayList(ProviderInfo.CREATOR);
ComponentName testName = (data.readInt() != 0)
? new ComponentName(data) : null;
String profileName = data.readString();
Bundle testArgs = data.readBundle();
IBinder binder = data.readStrongBinder();
IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder);
int testMode = data.readInt();
boolean restrictedBackupMode = (data.readInt() != 0);
Configuration config = Configuration.CREATOR.createFromParcel(data);
HashMap<String, IBinder> services = data.readHashMap(null);
bindApplication(packageName, info,
providers, testName, profileName,
testArgs, testWatcher, testMode, restrictedBackupMode,
config, services);
return true;
}
}
}
...
public final void bindApplication(String packageName, ApplicationInfo info,
List<ProviderInfo> providers, ComponentName testName,
String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode,
boolean restrictedBackupMode, Configuration config,
Map<String, IBinder> services) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeString(packageName);
info.writeToParcel(data, 0);
data.writeTypedList(providers);
if (testName == null) {
data.writeInt(0);
} else {
data.writeInt(1);
testName.writeToParcel(data, 0);
}
data.writeString(profileName);
data.writeBundle(testArgs);
data.writeStrongInterface(testWatcher);
data.writeInt(debugMode);
data.writeInt(restrictedBackupMode ? 1 : 0);
config.writeToParcel(data, 0);
data.writeMap(services);
mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
...
同理,这里的mRemote其实就是绑定的另一个Binder,也就是ApplicationThread,这里是ActivityManagerService利用ApplicationThreadProxy给ApplicationThread 传递消息。
然后在onTransact方法中接收到ApplicationThreadProxy传来的数据,然后调用ApplicationThread中的bindApplication方法,跟前面ActivityManagerProxy传递消息给ActivityManagerService的代码差不多的,我就不过多介绍了。接下来已经是在我们的App进程中了,得到ActivityManagerService消息之后的一些处理,这里我就不讲了。
到此为止,一来一回,详细的介绍了App进程与ActivityManagerService的交互过程。
总结
首先还是要自己先跟一遍源码,然后哪里卡住了,再看书,看文章,解决之后自己再跟一遍,这样就能对整个流程有较深刻的认识了。
源码还是要看的,万一以后要写个操作系统呢~