1.引言
利用几个星期的时间,搞懂以下几个问题:
- window 添加view的过程
- ActivityThread启动Activity得过程
- Instrumentation 类
- WindowManager 和Window的关系
- Dialog 和Activity 显示流程
- ViewRootImp学习
- WindowManagerImpl
- WindowManagerService 与WindowManager的交互
2.正题
transact():将 IBinder object 的引用跨进程传递到服务端,服务端回应客户端也会带上相同的IBinder 引用。transact() 是一个同步的过程,当执行到transact()得时候,会陷入阻塞状态;例如A进程向B进程通信,会将一个IBinder对象通过transact()方法发送到进程B,进程B运算好后,会调用onTransact将运算结果返回的IBinder对象,都是同一个引用。
public final boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (false) 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;
}
code参数决定了是发送数据还是接收数据。
onTransact()方法:
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (code == INTERFACE_TRANSACTION) {
reply.writeString(getInterfaceDescriptor());//推测是向远程进程发送数据
return true;
} else if (code == DUMP_TRANSACTION) {//Dump TRANSACTION 英文单词是卸载交流,大概意思就是接收到远程服务器换回 的值,
ParcelFileDescriptor fd = data.readFileDescriptor();
String[] args = data.readStringArray();//读取返回的结果
if (fd != null) {
try {
dump(fd.getFileDescriptor(), args);
} finally {
IoUtils.closeQuietly(fd);
}
}
// Write the StrictMode header.
if (reply != null) {
reply.writeNoException();
} else {
StrictMode.clearGatheredViolations();
}
return true;
} else if (code == SHELL_COMMAND_TRANSACTION) {
ParcelFileDescriptor in = data.readFileDescriptor();
ParcelFileDescriptor out = data.readFileDescriptor();
ParcelFileDescriptor err = data.readFileDescriptor();
String[] args = data.readStringArray();
ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
try {
if (out != null) {
shellCommand(in != null ? in.getFileDescriptor() : null,
out.getFileDescriptor(),
err != null ? err.getFileDescriptor() : out.getFileDescriptor(),
args, shellCallback, resultReceiver);
}
} finally {
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(err);
// Write the StrictMode header.
if (reply != null) {
reply.writeNoException();
} else {
StrictMode.clearGatheredViolations();
}
}
return true;
}
return false;
}
ActivityThread中的attach(false),方法涉及到通过Binder通信,如何进行通信的呢?
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault(); // 重点1
try {
mgr.attachApplication(mAppThread);// 重点2
} catch (RemoteException ex) {
// Ignore
}
// Watch for getting close to heap limit.
.............//省略
}
下面的是AMS与ApplicationThread 通过Binder通信中,一些相关的类:
ActivityManagerNative.getDefault() 返回的就是ActivityManagerNative的内部类ActivityManagerProxy,这个代理的构造方法需要传入一个服务端的IBinder。
ActivityManagerNative得gDefault 内部create方法有这么一句代码:
IBinder b = ServiceManager.getService("activity");
然后通过:asInterface()方法得到ActivityManagerProxy。
ActivityManagerProxy的attachApplication(applicationThread)代码如下:
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();
}
mRemote 就是我们上面ServiceManager.getService("activity")返回的,也就是AMS得BinderProxy,这个BinderProxy会将ApplicationThread的binder 传递到AMS进程,那么AMS就相当于拥有了ApplicationThread得引用。那么就可以远程调用了、
当客户端调用了startActivity得时候,会通过ipc与AMS通信,然后AMS调用Application得handleLaunchActivity(上面分析得到,AMS持有ApplicationThread得Binder)。进而执行了一下几个方法
Activity a = performLaunchActivity(r, customIntent);//方法1
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);//方法2
mInstrumentation.callActivityOnPause(r.activity);//方法3
handleResumeActivity 放先回调Activity的onResume方法,之后在将DecorView添加进Window。
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
}
关于java层Binder的调用顺序描述:
binder通信是一种client-server的通信结构,
1.从表面上来看,是client通过获得一个server的代理接口,对server进行直接调用;
2.实际上,代理接口中定义的方法与server中定义的方法是一一对应的;
3.client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象;
4.代理接口将该Parcel发送给内核中的binder driver.
5.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;
6.整个的调用过程是一个同步过程,在server处理的时候,client会block住。
参考文章:https://blog.csdn.net/coding_glacier/article/details/7520199
参考文章:http://weishu.me/2016/01/12/binder-index-for-newer/