Binder
Binder的组成结构
Binder的架构如图所示
ServiceManager负责把Binder Server注册到一个容器中。
我们可以这样理解Client、Server 、ServiceManager、Binder Driver之间的关系:
把ServiceManager比喻成电话局,存储着每个住宅的座机电话。张三给李四打电话,拨打电话号码,会转接到电话局,电话局的接线员查询到这个号码的地址,因为李四的电话号码之间在电话局注册过,所以能够拨通;如果没有注册,就会提示该号码不存在。
张三就是Client,李四就是Server,电话局就是ServiceManager,而接线员就是Binder Driver。
Binder的通信过程
Binder的通信过程和交互路线如下图所示
-
Server 在 ServiceManager 这个容器中注册
-
Client 想要调用 Server 的 add 方法,就需要先获取 Server 对象, 但是 ServiceManager 不会把真正的 Server 对象返回给 Client,而是把 Server 的一个代理对象返回给 Client ,也就是 Proxy
-
Client 调用 Proxy 的 add 方法,Binder驱动会帮他去调用 Server 的 add 方法,并把结果返回给 Client 。
AIDL
创建 Book 类
在主包下面建一个 aidl 包专门存放进程通讯用到的数据, Book 类继承 Parcelable 接口(原因:AIDL 只能传送继承 Parcelable 接口的类)
package com.example.zs.ipcdemo.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
private String bookId;
private String bookName;
public String getBookId() {
return bookId;
}
public void setBookId(String bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public static Creator<Book> getCREATOR() {
return CREATOR;
}
public Book(String bookId, String bookName) {
this.bookId = bookId;
this.bookName = bookName;
}
protected Book(Parcel in) {
bookId = in.readString();
bookName = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(bookId);
dest.writeString(bookName);
}
public void readFromParcel(Parcel in) {
bookId = in.readString();
bookName = in.readString();
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
}
创建 Book.aidl 、IBookManager.aidl
为什么要有 Book.aidl 类,因为只有将类在 aidl 中声明时候,AIDL 才能调用 Book 类。所以说要让 AIDL 能够传送自定义类需要 1、继承 Parcelable 接口 2、创建同名 .aidl 文件声明自己。
package com.example.zs.ipcdemo.aidl;
parcelable Book;
IBookManager.aidl 设置让客户端允许调用的接口。
package com.example.zs.ipcdemo.aidl;
import com.example.zs.ipcdemo.aidl.Book;
interface IBookManager{
List<Book> getBookList();
void addBook(in Book book);
}
这里面有个地方要注意一下 addBook 方法中有 in 这个类型,下面我们简单说一下 AIDL 文件中 in 类型out 类型和 inout 数据的区别。
- in :客户端的参数输入:是把实参的值赋值给行参 那么对行参的修改,不会影响实参的值 。
- out :服务端的参数输入:传递以后,行参和实参都是同一个对象,只是他们名字不同而已,对行参的修改将影响实参的值。
- inout:这个可以叫输入输出参数,客户端可输入、服务端也可输入。客户端输入了参数到服务端后,服务端也可对该参数进行修改等,最后在客户端上得到的是服务端输出的参数。
我们手动 ReBuild 一下我们的项目系统在这个目录下app\build\generated\source\aidl\debug 为我们自动生成 IBookManger.java ,接下来让我们看一下 IBookManger.java 的庐山真面目。
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: E:\\GitHub\\IPCDemo\\app\\src\\main\\aidl\\com\\example\\zs\\ipcdemo\\aidl\\IBookManager.aidl
*/
package com.example.zs.ipcdemo.aidl;
public interface IBookManager extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.example.zs.ipcdemo.aidl.IBookManager {
private static final java.lang.String DESCRIPTOR = "com.example.zs.ipcdemo.aidl.IBookManager";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.zs.ipcdemo.aidl.IBookManager interface,
* generating a proxy if needed.
*/
public static com.example.zs.ipcdemo.aidl.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.zs.ipcdemo.aidl.IBookManager))) {
return ((com.example.zs.ipcdemo.aidl.IBookManager) iin);
}
return new com.example.zs.ipcdemo.aidl.IBookManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR);
java.util.List<com.example.zs.ipcdemo.aidl.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
com.example.zs.ipcdemo.aidl.Book _arg0;
if ((0 != data.readInt())) {
_arg0 = com.example.zs.ipcdemo.aidl.Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.zs.ipcdemo.aidl.IBookManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public java.util.List<com.example.zs.ipcdemo.aidl.Book> getBookList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.example.zs.ipcdemo.aidl.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.example.zs.ipcdemo.aidl.Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override
public void addBook(com.example.zs.ipcdemo.aidl.Book book) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book != null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void registerListener(com.example.zs.ipcdemo.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((listener != null)) ? (listener.asBinder()) : (null)));
mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void unregisterListener(com.example.zs.ipcdemo.aidl.IOnNewBookArrivedListener listener) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((listener != null)) ? (listener.asBinder()) : (null)));
mRemote.transact(Stub.TRANSACTION_unregisterListener, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public java.util.List<com.example.zs.ipcdemo.aidl.Book> getBookList() throws android.os.RemoteException;
public void addBook(com.example.zs.ipcdemo.aidl.Book book) throws android.os.RemoteException;
}
刚看有点蒙逼,别急我们一步一步分析,IBookManager 文件中,包括 IBookManager.aidl 的两个接口,以及 Stub 和 Proxy 两个实现了 IBookManager 接口的类,其中 Stub 是定义在 IBookManager 接口中的,而 Proxy 则定义在 Stub 类中。
Client 执行流程
1、当服务连接建立完成后,客户端执行代码。IBookManager.Stub.asInterface(service)
这句代码的作用是判断传入的参数 IBinder
对象和自己是否在同一个进程如果不是则把这个IBinder
参数包装成一个 Proxy
对象,这时调用 Stub
的 getBookList()
方法,间接调用 Proxy
的 getBookList()
方法,看一下代码。
// 连接服务
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(final ComponentName name, IBinder service) {
// IBinder 通过 asInterface 判断
// asInterface方法的作用是判断参数——也就是IBinder对象,和自己是否在同一个进程:
// 是: 则直接转换、直接使用,接下来就跟 Binder 跨进程通信无关啦
// 否: 则把这个IBinder参数包装成一个 Proxy 对象,这时调用 Stub 的方法,间接调用Proxy的方法
IBookManager bookManager = IBookManager.Stub.asInterface(service);
try {
mBookManager = bookManager;
bookManager.getBookList();
Log.d(TAG, "get books count:" + bookManager.getBookList().size());
bookManager.registerListener(arrivedListener);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBookManager = null;
}
};
public static com.example.zs.ipcdemo.aidl.IBookManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
// 作用是判断传入的参数 IBinder 对象和自己是否在同一个进程
if (((iin != null) && (iin instanceof com.example.zs.ipcdemo.aidl.IBookManager))) {
return ((com.example.zs.ipcdemo.aidl.IBookManager) iin);
}
return new com.example.zs.ipcdemo.aidl.IBookManager.Stub.Proxy(obj);
}
2、Proxy
在自己的 getBookList()
方法中,会使用 Parcelable
来准备数据,把函数名称、函数参数都写入 _data
,让 _reply
接收函数返回值。最后使用 IBinder
的 transact
() 方法,把数据就传给 Binder
的 Server
端了。
@Override
public java.util.List<com.example.zs.ipcdemo.aidl.Book> getBookList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.example.zs.ipcdemo.aidl.Book> _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
// 通知服务器调用该方法
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
/** 调用mRemote.transact()方法后,Binder驱动会挂起当前客户端线程,
* 并向服务端发送一个消息,这个消息就包括客户端传递的参数。
* 服务端接收到消息,解析数据执行完相关任务后会把执行结果写入reply中,
**/ 然后向Binder驱动发送一个notify消息,Binder驱动从挂起处唤醒客户端线程继续执行。
_reply.readException();
_result = _reply.createTypedArrayList(com.example.zs.ipcdemo.aidl.Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
mRemote
指什么?
当一个Server Binder
被创建时其在Binder驱动中同时会创建一个mRemote
引用指向该Server。Client
端要访问Server
时首先要获取Server在Binder中的引用mRemote
,获取引用后就可以通过mRemote.transact()
方法向服务端发送消息。
transact
做了以下几件事
- 以线程间消息通信的模式向服务端发送客户端传递过来的参数。
- 挂起当前客户端线程,等待服务端线程执行完毕后的通知(notify)
- 接收服务端线程通知,继续执行客户端线程,并返回执行结果
Server 执行流程
Server 则是通过 onTransact() 方法接收 Client 进程传过来的数据,包括函数名称、函数参数,找到对应的函数,这里是 getBookList() ,把参数喂进去,得到结果,返回。所以 onTransact() 函数经历了读数据、执行要调用的函数、把执行结果再写数据的过程。
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
// 客户端调用指令 getBookList()
case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR);
// 调用本地服务 getBookList() 方法
java.util.List<com.example.zs.ipcdemo.aidl.Book> _result = this.getBookList();
reply.writeNoException();
// 将数据传给客户端
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR);
com.example.zs.ipcdemo.aidl.Book _arg0;
if ((0 != data.readInt())) {
_arg0 = com.example.zs.ipcdemo.aidl.Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addBook(_arg0);
reply.writeNoException();
return true;
}
return super.onTransact(code, data, reply, flags);
}
四大组件的工作原理
Activity的工作原理
App是怎样启动的
在手机屏幕上点击某个App的图标,假设是斗鱼app,这个APP的首页面就会展示在我们面前,看似简单的操作,背后经历了Activity和AMS的反反复复的通信过程。首选要搞清楚手机屏幕是一个Activity,这个Activity所在的app,业界称之为Launcher,Launcher是各大手机厂商提供的。
Launcher为每个app的图标提供了启动这个app所需要的Intent信息,如:包名、首页面地址、category等等,这些信息是app安装的时候,PackageManagerService
从各个apk包中的AndroidManifest
文件中读取到的。
启动流程
①Launcher通知ATMS,要启动斗鱼app,而且指定了启动app的哪个页面
②ATMS收到消息后,把要启动的页面记录下来
③Launcher当前页面进入Paused状态,然后通知ATMS,“你去找对应的app吧”
④ATMS检查斗鱼app是否已经启动了,是,则唤起斗鱼app,否,就要启动一个新的进程,ATMS所在的新进程中创建一个ActivityThread对象,启动相对应的main函数
⑤app启动后,通知ATMS,“我启动好了”
⑥ATMS翻出之前记录下的值(要启动的页面),告诉斗鱼app,启动这个页面
⑦斗鱼app启动首页,创建Context并与首页Activity关联,然后调用启动页面的Activity的onCreate函数
流程至此完成,分为两部分,1~3 阶段:Launcher和AMS相互通信,4~7阶段:斗鱼app与AMS相互通信
第一阶段:Launcher通知ATMS
点击Launcher上的app之后,会调用Launcher的startActivitySafely方法,其实还是会调用Activity的startActivity方法,startActivity方法中需要传入参数Intent,intent中带着要启动app所需要的关键信息,如:启动的页面类名等等,所以为什么要在Manifest中给首页面指定的action和category呢,就是在启动的时候Launcher会找到这个关键信息进行启动
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
# Launcher.java
@Override
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
@Nullable String sourceContainer) {
if (!hasBeenResumed()) {
addOnResumeCallback(() -> startActivitySafely(v, intent, item, sourceContainer));
if (mOnDeferredActivityLaunchCallback != null) {
mOnDeferredActivityLaunchCallback.run();
mOnDeferredActivityLaunchCallback = null;
}
return true;
}
// 调用了父类BaseDraggingActivity的startActivitySafely,最终会执行到父类Activity的startActivity
boolean success = super.startActivitySafely(v, intent, item, sourceContainer);
if (success && v instanceof BubbleTextView) {
BubbleTextView btv = (BubbleTextView) v;
btv.setStayPressed(true);
addOnResumeCallback(btv);
}
return success;
}
最终调用到Activity的startActivity方法:
# Activity.java
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)
&& mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
if (TextUtils.equals(getPackageName(),
intent.resolveActivity(getPackageManager()).getPackageName())) {
// Apply Autofill restore mechanism on the started activity by startActivity()
final IBinder token =
mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
// Remove restore ability from current activity
mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
// Put restore token
intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
}
}
if (options != null) {
//-1为requestCode表明不需要知道是否启动成功
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
启动app时候,调来调去最终会调用Activity的startActivityForResult方法,startActivityForResult的代码如下:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
//启动app时,因为是启动的第一个activity,所以mParent为空
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
//执行Instrumentation的execStartActivity
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
//向ActivityThread发送上一步的返回值
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
//省略部分代码
} else {
//省略部分代码
}
}
每个activity都持有一个Instrumentation对象,mMainThread变量,这是一个
ActivityThread
类型的变量,就是主线程,也就是UI线程,它代表了整个app,读者不禁要问,ActivityThread
代表了App应用程序,那么Application
类代表什么?其实,Application
对于android系统来说并没有那么重要,它只是个上下文,Application
是app的上下文,Context
是Activity
的上下文。
这个函数中传入了mMainThread.getApplicationThread(),它获取到的是ActivityThread的内部类ApplicationThread,这是一个Binder对象,代表了
launcher
所在的app进程,mToken
也是一个Binder
对象,代表launcher
这个Activity,也通过Instumentation
传给ATMS,ATMS查询记录就知道是谁向ATMS发送请求了,之后ATMS通过此对象(ApplicationThread)与app通信
查看
mInstrumentation.execStartActivity
方法,借助execStartActivity
,Activity会把数据传递给ActivityTaskManager
。
ActivityTaskManager.getService()
通过AIDL的方式得到IActivityTaskManager
,它是ActivityTaskManagerService
的binder引用,这里远程调用了ActivityTaskManagerService
的功能,它是一个实现了IInterface的接口,里面定义了四大组件的生命周期,启动Activity的时候,和ATMS通信机制是AIDL方式。
# Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
try {
// 流程就从Launcher进程进入到AMS所在的SystemServer进程了
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getBasePackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token,
target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
...
}
return null;
}
//=========ActivityTaskManager.java=========
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton = new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
//=================Singleton.java=========
/**
* Singleton helper class for lazily initialization.
* ......
*/
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
IActivityTaskManager是一个代理ATMS端Binder的对象,之后ATMS开始startActivity。 到这里Launcher向ATMS请求启动一个Activity的流程就结束了。
第二阶段:ATMS处理Launcher传过来的信息
1:Launcher通过AIDL和AMS进行通信,肯定每次是做不同的事,比如这次Launcher要启动斗鱼app,那么Launcher的startActivity方法最终都会通过拿到ATSM的代理IActivityTaskManager调用的startActivity,之后进入system server进程中的ATMS startActivity,ATMS 经过收集Intent信息知道要启动哪个Activity
2:AMS说:“好了,我知道了”,然后会检查AndroidManifest文件,检查是否存在要启动的Activity,如果不存在就抛出Activity not found异常信息
3:AMS通知Launcher:“没你什么事了,洗洗睡吧”,那么AMS是通过什么途径告诉Launcher的呢?结论是:AMS通过IApplicationThread的代理发送消息,而App端则通过ApplicationThread来接受这个消息,还是AIDL的方式。
回到代码,ActivityTaskManagerService
的 startActivity
调用最终调用了startActivityAsUser
,通过一系列 builder 获取 ActivityStarter 并设置对应参数,最终执行ActivityStarter的 execute方法,execute 函数的作用就是根据前面提供的的请求参数并开始启动应用
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
@Nullable String callingFeatureId, Intent intent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
assertPackageMatchesCallingUid(callingPackage);
enforceNotIsolatedCaller("startActivityAsUser");
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
// TODO: Switch to user app stacks here.
// getActivityStartController().obtainStarter获取到的是ActivityStarter
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setCallingFeatureId(callingFeatureId)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setUserId(userId)
.execute();
}
ActivityStarter
ActivityStarter:专门负责一个 Activity 的启动操作。它的主要作用包括解析 Intent、创建 ActivityRecord、如果有可能还要创建 TaskRecord
obtainStarter 返回的类型是 ActivityStarter,其 execute 函数的作用就是根据前面提供的的请求参数并开始启动应用。
关键调用路径:
execute
===>>executeRequest
====>>startActivityUnchecked
===>>startActivityInner
- exexute: 处理 Activity 启动请求的接口;
- executeRequest: 执行一系列权限检查,对于合法的请求才继续;
- startActivityUnchecked: 调用该方法时表示大部分初步的权限检查已经完成,执行 Trace,以及异常处理;
- startActivityInner: 启动 Activity,并更新全局的 task 栈帧信息;
忽略 ActivityStack、WindowContainer 等任务窗口管理的代码,只关注其中真正启动应用相关的:
- mRootWindowContainer.resumeFocusedTasksTopActivities()
resumeFocusedStacksTopActivities
()先将目标Activity Stack移到前台,然后创建好Activity后放到Stack里,用户就能直接看到了,所以,创建Activity的逻辑还在resumeFocusedStacksTopActivities()中
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!mStackSupervisor.readyToResume()) { return false;}
......
if (targetStack != null && (targetStack.isTopStackInDisplayArea()
|| getTopDisplayFocusedStack() == targetStack)) {
result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
ActivityStack
ActivityStack:管理TaskRecord的,包含了多个TaskRecord · ActivityStackSupervisor:管理ActivityStack
resumeTopActivityUncheckedLocked
===>>resumeTopActivityInnerLocked
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
if (mResumedActivity != null) {
// 暂停Launcher
pausing |= startPausingLocked(userLeaving, false , next);
}
// 启动Activity
mStackSupervisor.startSpecificActivity(next, true, true);
...
}
startPausingLocked方法主要是通知Launcher进入Pause状态。前面我们了解了Launcher与ATMS的通信,现在我们看看ATMS是如何与Launcher通信的?
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean pauseImmediately) {
..........
if (prev.app != null && prev.app.thread != null) {//条件满足
............
try {
............
//下面的代码,就是暂停Launcher,这是AMS与ActivityThread交互的内容,暂时不讨论
//prev.appToken为IApplicationToken.Stub,prev.finishing为false,userLeaving为true,异步执行
mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
.........
}
} else {
............
}
............
mService是ATMS
mService.getLifecycleManager()返回的是ClientLifecycleManager;
PauseActivityItem继承自ActivityLifecycleItem,它封装了一系列将要进行IPC的操作;
ClientLifecycleManager
该类能够组合多个生命周期转换请求和/或回调,并将它们作为单个事务执行。主要作用就是生命周期的管理调用。
void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
@NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
//ClientTransaction封装传进来的参数
final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
stateRequest);
//执行传输操作
scheduleTransaction(clientTransaction);
}
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
//client就是IApplicationThread
final IApplicationThread client = transaction.getClient();
//下面这句代码就是跨进程了
transaction.schedule();
if (!(client instanceof Binder)) {
transaction.recycle();
}
}
调用ClientTransaction .schedule():
public void schedule() throws RemoteException {
//mClient就是IApplicationThread,接下来会通过IPC的方式调用
//Launcher的ActivityThread.ApplicationThread.scheduleTransaction方法;
//从AMS进程,进入App进程
mClient.scheduleTransaction(this);
}
这里开始,实际就是从系统进程回到了应用进程。
IApplicationThread:是系统进程持有的app进程中ApplicationThread的Binder代理对象。
mClient.scheduleTransaction()方法的实现在客户端的ApplicationThread中,接下来就要进入ActivityThread.ApplicationThread了;
ApplicationThread
ApplicationThread:ActivityThread的内部类。AMS通过binder代理调用到ApplicationThread中的方法后,通过主线程(ActivityThread中的main方法)中开启的handler消息轮询来通知主线程调用相关方法。主线程的相关生命周期方法的具体实现会委托给Instrumentation类实现,在Instrumentation类中,会调用具体组件的相关生命周期方法。
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
//终于从AMS进程,进入到了App进程
ActivityThread.this.scheduleTransaction(transaction);
}
void scheduleTransaction(ClientTransaction transaction) {
//准备工作,它会执行ActivityLifecycleItem的preExecute()方法,这里就是PauseActivityItem
transaction.preExecute(this);
//发送通知,由ActivityThread接收
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
ApplicationThread向ActivityThread的H发送了一个EXECUTE_TRANSACTION消息,ActivityThread与ApplicationThread之间通过Handler来通信。
case EXECUTE_TRANSACTION:
//取出传递过来的ClientTransaction
final ClientTransaction transaction = (ClientTransaction) msg.obj;
//执行transaction
mTransactionExecutor.execute(transaction);
if (isSystem()) {
transaction.recycle();
}
break;
拿到ATMS端的ClientTransaction,调用mTransactionExecutor.execute(transaction):
public void execute(ClientTransaction transaction) {
//token就是IApplicationToken.Stub
final IBinder token = transaction.getActivityToken();
//执行Callbacks,后面分析的LaunchActivityItem就是在这里执行的,本例中暂时没有Callbacks
executeCallbacks(transaction);
//我们要看的是这个
executeLifecycleState(transaction);
mPendingActions.clear();
}
private void executeLifecycleState(ClientTransaction transaction) {
//得到ActivityLifecycleItem,本例中是PauseActivityItem
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
log("Resolving lifecycle state: " + lifecycleItem);
//得到token
final IBinder token = transaction.getActivityToken();
final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (r == null) {
// Ignore requests for non-existent client records for now.
return;
}
//Activity.onStart方法就是在这里面调用的,后面会看到;
//本次流程中的lifecycleItem是PauseActivityItem,所以lifecycleItem.getTargetState()为4;
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
//将动作传递给lifecycleItem执行,lifecycleItem在AMS进程当中,这里又进行了IPC
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
//上面的execute方法主要是app进程中的pause操作,当app进程中的pause操作结束之后,需要通知AMS进程,进行下一步操作
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
①cycleToPath():
比如某一个Activity A,它现在的生命周期是onCreate阶段,用1来表示;lifecycleItem.getTargetState()跟lifecycleItem的类型有关,PauseActivityItem与ResumeActivityItem的getTargetState()返回值是不一样的,假如这里的lifecycleItem是ResumeActivityItem,ResumeActivityItem对应的生命周期是Activity的onResume,那lifecycleItem.getTargetState()的返回值是3,由于onCreate代表1,1和3之间差个2,所以onCreate和onResume中间还差一个生命周期,这个生命周期就是onStart();
经过一系列的方法调用 execute ===>> executeLifecycleState ===> cycleToPath ===> lifecycleItem.execute
调用到了PauseActivityItem.execute()
方法
PauseActivityItem.java
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
//client是在app进程中的,ActivityThread实现了ClientTransactionHandler.handlePauseActivity()方法
client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
"PAUSE_ACTIVITY_ITEM");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
又回到了ActivityThread.handlePauseActivity():
ActivityThread.java
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges, PendingTransactionActions pendingActions, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
if (userLeaving) {//成立
//调用onUserInteraction()和onUserLeaveHint()函数
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
//执行暂停Launcher的操作
performPauseActivity(r, finished, reason, pendingActions);
// Make sure any pending writes are now committed.
//isPreHoneycomb()判断SDK版本是否是HONEYCOMB之前的版本
if (r.isPreHoneycomb()) {
//等待要暂停的应用进程的异步操作完成,保持数据完整
QueuedWork.waitToFinish();
}
mSomeActivitiesChanged = true;
}
}
private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
PendingTransactionActions pendingActions) {
...
final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
//暂停前保存状态
if (shouldSaveState) {
//调用onSaveInstanceState()保存Activity的状态
callActivityOnSaveInstanceState(r);
}
//真正的暂停执行操作在这里
performPauseActivityIfNeeded(r, reason);
//通知OnActivityPausedListener执行其监听操作
ArrayList<OnActivityPausedListener> listeners;
synchronized (mOnPauseListeners) {
listeners = mOnPauseListeners.remove(r.activity);
}
int size = (listeners != null ? listeners.size() : 0);
for (int i = 0; i < size; i++) {
listeners.get(i).onPaused(r.activity);
}
final Bundle oldState = pendingActions != null ? pendingActions.getOldState() : null;
if (oldState != null) {
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
return shouldSaveState ? r.state : null;
}
继续看performPauseActivity()中的performPauseActivityIfNeeded(r, reason):
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
...
try {
r.activity.mCalled = false;
//重点在这里,Activity.onPause方法的调用
mInstrumentation.callActivityOnPause(r.activity);
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException("Unable to pause activity "
+ safeToComponentShortString(r.intent) + ": " + e.toString(), e);
}
}
//设置当前的状态为ON_PAUSE
r.setState(ON_PAUSE);
}
ActivityThread将暂停工作委托给了Instrumentation,每个Activity都持有一个Instrumentation,最后又交给了Activity的performPause
Instrumentation.java
public void callActivityOnPause(Activity activity) {
activity.performPause();
}
Activity.java
final void performPause() {
mDoReportFullyDrawn = false;
//改变Fragment的状态
mFragments.dispatchPause();
mCalled = false;
//调用Activity的生命周期onPause()方法
onPause();
writeEventLog(LOG_AM_ON_PAUSE_CALLED, "performPause");
//此时已经是非mResumed状态
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()");
}
}
总结
通过 IApplicationThread 的 schedulePauseActivity 方法发起 binder 跨进程调用,进入到应用进程的 ApplicationThread 的 schedulePauseActivity 方法(该方法运行在客户端的 binder 线程池里面),再经过 mH 将数据切换到应用进程的主进程中执行,由 ActivityThread 的 handlePauseActivity 方法处理,再经过 performPauseActivity 内部调用 Instrumentation 的 callActivityOnPause 方法,内部会调用 Activity 的 performPause 方法,会回调 Launcher 的 onPause 方法。
第三阶段:Launcher去休眠,然后通知ATMS,“我休眠了
当Launcher处于onPause状态后,需要通知AMS进程,进行下一步操作,调用PauseActivityItem.postExecute():
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
if (mDontReport) {
return;
}
try {
//调用ATMS的activityPaused()方法
ActivityTaskManager.getService().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
第四阶段:ATMS启动新的进程
ATMS接下来要启动斗鱼App的首页,因为此app不在后台进程中,所以要启动一个新的进程,这里调用的是Process.start方法,并且指定了ActivityThread的main函数为入口函数。
ActivityStack.resumeTopActivityInnerLocked ===>> startSpecificActivity
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// 获取启动的activity进程信息
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
//如果进程存在,并且进程中有线程存在,就启动一个同应用的activity
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, 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.
knownToBeDead = true;
}
//否则通过AMS向Zygote进程请求创建新进程
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
第五阶段:新进程启动,以ActivityThread的main函数为入口
启动新进程,就是启动一个新的app,为这个进程创建ActivityThread对象,这就是我们熟悉的UI主线程。创建好UI线程后,立刻进入ActivityThread的main函数,接下来要做两件具有重大意义的事:
-
①创建一个主线程Looper,也就是MainLooper,MainLooper就是在这里创建的
-
②创建Applicaition,Application也是在这里创建的
public static void main(String[] args) {
............
//设置临时进程名为<pre-initialized>
Process.setArgV0("<pre-initialized>");
//准备UI主线程的消息循环
Looper.prepareMainLooper();
............
//创建ActivityThread,并调用attach 方法,传入的参数为false
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
............
/// M: ANR Debug Mechanism
mAnrAppManager.setMessageLogger(Looper.myLooper());
//进入主线程消息循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
创建了ActivityThread,并调用attach方法:
final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system, long startSeq) {
......
if (!system) {
//这一步是获取AMS实例
final IActivityManager mgr = ActivityManager.getService();
//然后跨进程通信
mgr.attachApplication(mAppThread, startSeq);
}
}
通过获取AMS,进行跨进程通信,调用AMS的attachApplication方法
在AMS.attachApplication()中,会调用ActivityThread.ApplicationThread.bindApplication():
public final void bindApplication(String processName, .........) {
............
//bindApplication将ActivityManagerService传入的数据封装到AppBindData中
AppBindData data = new AppBindData();
data.processName = processName;
............
//通过BIND_APPLICATION消息发送给应用程序主线程的消息循环中,由ActivityThread的H.handleMessage处理。
sendMessage(H.BIND_APPLICATION, data);
}
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
private void handleBindApplication(AppBindData data) {
............
// 创建一个对应的`LoadedApk`对象
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
//创建并初始化应用程序的ContextImpl
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
updateLocaleListFromAppContext(appContext,
mResourcesManager.getConfiguration().getLocales());
............
if (ii != null) {
............
} else {
//创建并且初始化mInstrumentation
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
}
............
Application app;
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
try {
//创建应用程序Application,对应AndroidManifest.xml的Application
app = data.info.makeApplication(data.restrictedBackupMode, null);
app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
//将第一个Application视为进程的初始Application
mInitialApplication = app;
//安装该应用程序的ContentProvider
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
try {
//调用Instrumentation的onCreate方法
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
............
}
try {
//调用Application的onCreate方法
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
............
}
} finally {
............
}
............
}
//Application.java
public void onCreate() {
}
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
return getPackageInfo(ai, compatInfo, null, false, true, false);
}
通过 getPackageInfoNoCheck() 创建LoadedApk对象并保存在data.info。
通过data.info.makeApplication(data.restrictedBackupMode, null)创建了Application。
通过mInstrumentation.callApplicationOnCreate(app)调用了app.onCreate();,Application创建完成。
主线程在收到BIND_APPLICATION
消息后,根据传递过来的ApplicationInfo
创建一个对应的LoadedApk
对象(标志当前apk信息),然后创建ContextImpl
对象(标志当前进程环境),紧接着通过反射创建目标Application,并调用其attach方法,将ContextImpl对象设置为目标Applcation的上下文环境,最后调用Application的onCreate
函数,做一些初始化工作
App的灵魂是ActivityTread
,也就是主线程,app开发人员用不到,但使用反射是可以修改这个类的一些行为的。
APP的bindApplication,主要初始化了AppBindData,然后发送BIND_APPLICATION给APP的主线程BIND_APPLICATION,最后执行了handleBindApplication,该方法主要在App进程中对App的一些硬件资源配置申请的属性、App的文件夹等完成App基本信息的初始化
ATMS的attachApplication
创建App的最后就是要告诉ATMS,“我启动好了”,同时把自己的ActivityThread
对象发送给ATMS,ATMS电话簿中就多了这个新的App登记信息,ATMS以后就通过这个ActivityThread对象,向这个App发送消息。这部分代码是在:
//ActivityManagerService.java:
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
long bindApplicationTimeMillis;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
......
final String processName = app.processName;
......
final BackupRecord backupTarget = mBackupTargets.get(app.userId);
try {
......
mAtmInternal.preBindApplication(app.getWindowProcessController());
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
if (app.isolatedEntryPoint != null) {
// This is an isolated process which should just call an entry point instead of
// being bound to an application.
thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
} else if (instr2 != null) {
thread.bindApplication(processName, appInfo, providers,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions);
}
.......
} catch (Exception e) {
......
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
// mAtmInternal.attachApplication()最终调用的是ATMS中的 attachApplication()。
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
......
return true;
}
在ATMS的attachApplication()中,通过IPC的方式进行了ActivityThread.ApplicationThread.bindApplication()之后,会调用mStackSupervisor.attachApplicationLocked(app),mStackSupervisor就是ActivityStackSupervisor,最后调用ActivityStackSupervisor的realStartActivityLocked方法
- 这里完善了ActivityRecord,设置了进程等信息。总体上可以理解,应为ActivityRecord、ProcessRecord等由AMS/ATMS管理,这里将application绑定到了ATMS。
- 创建了ClientTransaction对象
- 设置了ClientTransaction的callback,为一个创建的LaunchActivityItem对象
- 设置生命周期,为创建的lifecycleItem对象
- 通过mService.getLifecycleManager().scheduleTransaction(clientTransaction)发送请求。这里的mService为ATMS,这里的mService.getLifecycleManager()即ClientLifecycleManager。
- 创建Application后,通过attachApplication()绑定到ATMS。当前还是在系统进程中。
第六阶段:ATMS告诉新App要启动哪个Activity
ATMS把传入的ActivityThread对象转为一个ApplicationThread对象,用于以后和这个App跨进程通信,在第六阶段AtMS从过去记录中翻出来要启动哪个Activity,然后通过ATP告诉App
在ActivityStackSupervisor的realStartActivityLocked方法中,通过mService.getLifecycleManager().scheduleTransaction(clientTransaction)发送请求,即调用了ClientLifecycleManager发送请求。
接下来的流程就和暂停Launcher时一样,查看ClientLifecycleManager的scheduleTransaction方法:
//ClientLifecycleManager.java:
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}
//ClientTransaction.java
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
mClient是一个IApplicationThread接口,上面我们也分析到,它的实现是ApplicationThread,这里又回到了ActivityThread,
ApplicationThread.scheduleTransaction ===>> ClientTransactionHandler.scheduleTransaction
public abstract class ClientTransactionHandler {
// Schedule phase related logic and handlers.
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
scheduleTransaction方法中发送了EXECUTE_TRANSACTION消息给ActivityThread的H类处理
android.app.ActivityThread
// An executor that performs multi-step transactions.
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
......
class H extends Handler {
......
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
......
}
通过handleMessage来处理这个消息,里面又调用了TransactionExecutor的execute方法:
public void execute(ClientTransaction transaction) {
...
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
}
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
...
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
// 在上面realStartActivityLocked()中,设置的callback是LaunchActivityItem对象。这里execute()最终执行到LaunchActivityItem的execute()。
final ClientTransactionItem item = callbacks.get(i);
...
item.execute(mTransactionHandler, token, mPendingActions);
}
}
private void executeLifecycleState(ClientTransaction transaction) {
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
//生命周期的过渡
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
在上面realStartActivityLocked()中,设置的callback是LaunchActivityItem对象。这里execute()最终执行到LaunchActivityItem的execute()。
//LaunchActivityItem.java:
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client, mAssistToken);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
这里的client就是ActivityThread。所以走到了ActivityThread的handleLaunchActivity()
//ActivityThread.java:
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
......
final Activity a = performLaunchActivity(r, customIntent);
......
return a;
}
接着看
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// 创建Activity实例
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);
}
}
......
执行attach,内部创建Window等
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, window, r.configCallback,
r.assistToken);
......
// 执行了Activity的onCreate()方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
......
}
经过一系列的方法调用execute->executeCallbacks->cycleToPath->performLifecycleSequence,我们终于看到了熟悉的东西,一堆Activity的生命周期。
长话短说,主要流程为:
- 创建应用上下文(Context),获取 ClassLoader;
- 创建 Activity 对象,实质上是 classLoader.loadClass(name).newInstance(),这里会对 Activity 类进行初始化,调用对象的 方法,从而执行目标类里 static block 中的代码;
- 根据应用的 AndroidManifest.xml 创建 Application对象,并调用其 onCreate 回调;
- 调用对应 Activity 的 onCreate 回调;
第七阶段:启动斗鱼首页Activity
android.app.ActivityThread
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
......
final Activity a = performLaunchActivity(r, customIntent);
......
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
关键代码1
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);
}
}
......
执行attach,内部创建Window等
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, window, r.configCallback,
r.assistToken);
......
关键代码2
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
......
}
performLaunchActivity方法要做的是哪些事?
①通过Instrumentati0on的newActivity方法,创建要启动的Activity实例。
②为这个Acctivity创建一个上下文Context对象,并与Activity进行关联
③通过Instrumentaction的callActivityOnCreate方法,执行Activity的onCreate方法,从而启动Activity,至此App启动完毕,这个流程是经过多次握手,App和ATMS频繁的向对方发送消息,而发送消息的机制,是建立在Binder的基础之上的。
App内部的页面跳转
接下来我们看App内部页面的跳转。
从ActivityA跳转到ActivityB,其实可以把ActivityA看作是Launcher,那么这个跳转过程,和App的启动过程就很像了。
有了前面的分析基础,会发现,这个过程不需要重新启动一个新的进程,所以可以省略App启动过程中的一些步骤,流程简化为:
- ActivityA向AMS发送一个启动ActivityB的消息。
- AMS保存ActivityB的信息,然后通知App,你可以休眠了(onPaused)。
- ActivityA进入休眠,然后通知AMS,我休眠了。
- AMS发现ActivityB所在的进程就是ActivityA所在的进程,所以不需要重新启动新的进程,所以它就会通知App,启动ActivityB。
- App启动ActivityB。
以上的分析,仅限于ActivityA和ActivityB在相同的进程中,如果在Manifest中指定这两个Activity不在同一个进程中,那么就又是另一套流程了,但是整体流程大同小异。
Context家族史
Activity和Service都有Context,这三个类,还有Application,其实是亲戚一家子。
Activity因为有了一层Theme,所以中间有个ContextThemeWrapper,相当于它是Service和Application的侄子。
ContextWrapper只是一个包装类,没有任何具体的实现,真正的逻辑都在ContextImpl里面。
一个应用包含的Context个数:Service个数+Activity个数+1(Application类本身对应一个Context对象)。
应用程序中包含多个ContextImpl对象,而其内部变量mPackageInfo指向同一个PackageInfo对象。
Activity 和 Context的区别
我们就拿Activity举例子,看看Activity和Context的联系和区别。
我们知道,跳转到一个新的Activity要这么写:
我们还知道,也可以在Activity中使用getApplicationContext
方法获取Context上下文信息,然后使用Context 的startActivity方法,启动一个新的Activity:
这二者的区别是什么?
Activity中:
@Override
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中无论是使用哪一种startActivity方法都会调用到Activity自身的方法,所以是一样的。
然而在其他的Context子类,例如ContextImpl.java中的实现,会检查有没有设置Flag:FLAG_ACTIVITY_NEW_TASK,否则会报错:
ContextImpl中:
@Override
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
// Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
// generally not allowed, except if the caller specifies the task id the activity should
// be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
// maintain this for backwards compatibility.
final int targetSdkVersion = getApplicationInfo().targetSdkVersion;
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
&& (targetSdkVersion < Build.VERSION_CODES.N
|| targetSdkVersion >= Build.VERSION_CODES.P)
&& (options == null
|| ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity) null, intent, -1, options);
}