IMS创建完毕之后,在SystemServer里面会用其来构建WMS。之前已经看到,构造WMS的时候将IMS传了进去
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy) {
mInputManager = inputManager;
if(mInputManager != null) {
final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
mPointerEventDispatcher = inputChannel != null
? new PointerEventDispatcher(inputChannel) : null;
} else {
mPointerEventDispatcher = null;
}
}
IMS-->monitorInput方法
public InputChannel monitorInput(String inputChannelName) {
if (inputChannelName == null) {
throw new IllegalArgumentException("inputChannelName must not be null.");
}
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
inputChannels[0].dispose(); // don't need to retain the Java object reference
return inputChannels[1];
}
InputChannel用于从InputDispatcher中获取所有的input消息,所以这里构造一对InputChannel,其中index为0的代表server端,index为1的代表client端,一个注册到底层的InputDispatcher中,一个用于PointerEventDispatcher给上层分发消息。
PointerEventDispatcher的构造,它是用来分析点击事件的
public class PointerEventDispatcher extends InputEventReceiver {
ArrayList<PointerEventListener> mListeners = new ArrayList<PointerEventListener>();
PointerEventListener[] mListenersArray = new PointerEventListener[0];
public PointerEventDispatcher(InputChannel inputChannel) {
super(inputChannel, UiThread.getHandler().getLooper());
}
PointerEventDispatcher继承InputEventReceiver
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
nativeInit函数首先获取Java层传入的InputChannel和MessageQueue对象,然后构造NativeInputEventReceiver对象并调用它的initialize方法将InputChannel[1]与UiThread的looper绑定起来。
NativeInputEventReceiver的consumeEvents最终调用InputEventReceiver的dispatchInputEvent方法将此次触摸事件传递给Java层。然后,PointerEventDispatcher的onInputEvent方法将会被调用
// Called from native code.
@SuppressWarnings("unused")
private void dispatchInputEvent(int seq, InputEvent event, int displayId) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event, displayId);
}
@Override
public void onInputEvent(InputEvent event, int displayId) {
try {
if (event instanceof MotionEvent
&& (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
final MotionEvent motionEvent = (MotionEvent) event;
PointerEventListener[] listeners;
synchronized (mListeners) {
if (mListenersArray == null) {
mListenersArray = new PointerEventListener[mListeners.size()];
mListeners.toArray(mListenersArray);
}
listeners = mListenersArray;
}
for (int i = 0; i < listeners.length; ++i) {
listeners[i].onPointerEvent(motionEvent, displayId);
}
}
} finally {
finishInputEvent(event, false);
}
所以接收到底层传上来的Input消息,必须实现InputEventReceiver
View中如何接收到触摸事件
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
@Override
public void onInputEvent(InputEvent event, int displayId) {
/// M: record current key event and motion event to dump input event info for
/// ANR analysis. {
ViewDebugManager.getInstance().debugInputEventStart(event);
/// }
enqueueInputEvent(event, this, 0, true);
}