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/