1.客户端注册事件监听
我们知道当我们展示一个窗口时候,WindowManager会添加Decorview对应的IWindow到wms,这当中就会发生触摸事件的注册到InputManager
WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
...
View panelParentView = null;
...
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
...
root.setView(view, wparams, panelParentView);
...
}
核心代码是mWindowSession.addToDisplay(..., mInputChannel);这是一个Binder会调用到Wms中,在wms给mInputChannel内部成员赋值,传回到app,然后WindowInputEventReceiver监听mInputChannel是否有值,有的话回调WindowInputEventReceiver
ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
requestLayout();
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
mInputChannel = new InputChannel();
}
...
//addToDisplay发起Binder调用,wms端肯定也会有对应函数响应
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
...
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
...
}
2.WMS服务端对应处理
wms端肯定也会有对应函数响应
Session.java
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
Rect outOutsets, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
...
//APP端每一个窗口对应一个wms端一个WindowState
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
if (openInputChannels) {
win.openInputChannel(outInputChannel);
}
...
}
这一步创建了一个socketpair,返回来俩个socket即 InputChannel[0],inputChannels[1] ;inputChannels[1]给客户端传来的outInputChannel赋值,InputChannel[0]注册给InputManagerService,当有输入事件的时候InputManagerService发送事件给InputChannel[0],然后app端在outInputChannel接受事件
WindowState.java
void openInputChannel(InputChannel outInputChannel) {
String name = getName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
mInputWindowHandle.inputChannel = inputChannels[0];
if (outInputChannel != null) {
//把app端传过来的outInputChannel赋值
mClientChannel.transferTo(outInputChannel);
mClientChannel.dispose();
mClientChannel = null;
} else {
// If the window died visible, we setup a dummy input channel, so that taps
// can still detected by input monitor channel, and we can relaunch the app.
// Create dummy event receiver that simply reports all events as handled.
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
}
mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
}
3总结
App添加窗口时会向wms请求,wms会创建一个socketpair的俩端一个端发给返回app,一端注册到InputManagerService中,当InputManagerService收到事件的时候就会通过socket夸进程通信,传回app端对应窗口