从你触摸屏幕开始分析android触摸事件分发

本篇只会讲到触发ViewGroup的dispatchTouchEvent为止,因为接下去的一搜一大把,或者说有点基础的应该都了解。

  • 从触摸开始

    首先,请你打开命令行工具。输入adb shell进入到shell命令,然后输入getevent,会监听打印触摸屏幕的event信息。

add device 1: /dev/input/event5
name: "msm8974-taiko-mtp-snd-card Headset Jack"
add device 2: /dev/input/event4
name: "msm8974-taiko-mtp-snd-card Button Jack"
add device 3: /dev/input/event3
name: "hs_detect"
add device 4: /dev/input/event1
name: "touch_dev"
add device 5: /dev/input/event0
name: "qpnp_pon"
add device 6: /dev/input/event2
name: "gpio-keys"

   当你使出你的一阳指点击屏幕的时候,变回不断的去获取到你的点击事件,就像这样:

/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0039 000005cf
/dev/input/event1: 0003 0035 0000020b
/dev/input/event1: 0003 0036 0000068d
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0036 0000068c
/dev/input/event1: 0003 0030 00000005
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0039 ffffffff
/dev/input/event1: 0000 0000 00000000

  这些操作全都是Linux Kernel去做的,只要你点击了屏幕了,硬件设备变回产生硬件终端,Kernel收到硬件终端之后,会对其进行加工,包装成event事件之后添加到/dev/input/目录下,就像如上所示的event1。
  
 [](http://www.cnblogs.com/tnxk/archive/2012/10/26/2741326.html)
* ####Android系统的监听
  Android会不断的去监控/dev/input/目录下的所有的设备节点,一旦发现有新的设备节点可读时就会立马读出事件并进行处理。

    * ######WMS
  而这里的复杂步骤涉及到frameWork层,我们就从WMS开始吧,
  先是有SystemServer启动的WMS。SystemServer.java的startOtherServices()

wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);

并且同样在这个方法中初始化了InputManagerService,掌管输入事件的服务。

inputManager = new InputManagerService(context);

我们看到`WindowManagerService`的main方法传入的就是这个inputManager。
在InputManagerService的构造方法中,用到了
    mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
native的方法,nativce层不是重点,我这边就快速的将过去了。
在`frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp`中(没有在本地编译过源码的同学可以去 http://androidxref.com/ 查看,基于当前最新的7.1.1)

static jlong nativeInit(JNIEnv* env, jclass /* clazz /,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
NativeInputManager
im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
eturn reinterpret_cast(im);
}

然后看内部类nativeInputManger

NativeInputManager::NativeInputManager(jobject contextObj,
...
sp eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}

我们看到创建了一个EventHub类,并且将其交给InputManger并生成一个InputManger对象。
/frameworks/native/services/inputflinger/InputManager.cpp

InputManager::InputManager(
const sp& eventHub,
const sp& readerPolicy,
const sp& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}

一个分发对象,一个reader对象,并且调用initialize方法

void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

创建读线程和分发线程

   至此,所有的初始化先都ok了,在SystemServer.java,创建了InputManagerService之后没几行就调用了            `inputManager.start();`,

public void start() {
...
nativeStart(mPtr);
...
}

又看到了native。。。来吧继续相当枯燥的native,我要快进了,我有点写的想吐。。
`frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp`

static void nativeStart(JNIEnv* env, jclass /* clazz /, jlong ptr) {
NativeInputManager
im = reinterpret_cast(ptr);

    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }

}

`/frameworks/native/services/inputflinger/InputManager.cpp
`

status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}

    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    if (result) {
        ALOGE("Could not start InputReader thread due to error %d.", result);

        mDispatcherThread->requestExit();
        return result;
    }

    return OK;

}

启动了读线程和分发线程
`/frameworks/native/services/inputflinger/InputReader.cpp`

bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
...
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
...
}

不断的loop去通过EventHub去getEvents(越来越偏了,getEvents不继续往下了,知道这个深度已经对于非framework工程师来说已经够了)
在getEvents方法中去从dev/input/目录下读取设备节点并加工,并返回给InputReader进行处理。

          之后的处理过程以及一系列跳转也是相当复杂,由于本文的初衷并非详解最底层的东西,
          故而此处一并略过直接到底层将event回传给java层的最末

    * ######InputEventReceiver
   在此我们只需要知道由InputChannel构建起了UI进程和底层system_server进程的socket通道。
   最终会从NativeInputEventReceiver.cpp处调起InputEventReceiver的方法
// Called from native code.
@SuppressWarnings("unused")
private void dispatchInputEvent(int seq, InputEvent event) {
    mSeqMap.put(event.getSequenceNumber(), seq);
    onInputEvent(event);
}
    InputEventReceiver是个抽象类,我们在ViewRootImpl中定义了如下

final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}

    @Override
    public void onInputEvent(InputEvent event) {
        enqueueInputEvent(event, this, 0, true);
    }

    @Override
    public void onBatchedInputEventPending() {
        if (mUnbufferedInputDispatch) {
            super.onBatchedInputEventPending();
        } else {
            scheduleConsumeBatchedInput();
        }
    }

    @Override
    public void dispose() {
        unscheduleConsumeBatchedInput();
        super.dispose();
    }
}
那么我们就看看enqueueInputEvent到底做了些什么操作:

void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
...
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
void doProcessInputEvents() {
while (mPendingInputEventHead != null) {
...
deliverInputEvent(q);
}
...
}
private void deliverInputEvent(QueuedInputEvent q) {
...
if (stage != null) {
stage.deliver(q);
} else {
finishInputEvent(q);
}
}

最终就在这个deliver方法中,而这个stage是个InputStage对象,这个类内部是链表结构,最终会将q分发到可以处理的窗口ViewPostImeInputStage,由它的processPointerEvent方法来处理

private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
final View eventTarget =
(event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ?
mCapturingView : mView;
...
boolean handled = eventTarget.dispatchPointerEvent(event);
...
return handled ? FINISH_HANDLED : FORWARD;
}

调用的view的dispatchPointerEvent方法:

public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}

而我们知道,window的最底层的View就是DecorView,那么这个时候调用的应该就是DecorView的dispatchTouchEvent方法

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final Window.Callback cb = mWindow.getCallback();
return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
}

还记的callBack是谁么,在Activity的attach方法中,`mWindow.setCallback(this);
`
这个callback就是activity本身,所以我们要去Activity中查看它的dispatchTouchEvent方法

public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}

这里分了两步,先去getWindow().superDispatchTouchEvent(ev),这一步会从PhoneWindow->DecorView->ViewGroup(DecorView继承FrameLayout就是ViewGroup),最后实际上是触发了ViewGroup的dispatchTouchEvent方法,也就是activity会先将事件交给DecorView去处理,如果被消耗掉,就返回true。如果没有消耗这个事件,就回调Activity自己的onTouchEvent。

    * ######总结
那么把上面的一大坨我们简略的来讲如下的流程:
   * 用户触摸屏幕产生设备节点中断并保存到/dev/input/目录下
   * 底层的EventHub监听目录,将事件读出并加工返回给随着WMS一起启动的底层的InputReader
   * InputReader处理加工之后交给InputDispatcher来进行分发,通过socket通知UI进程的InputEventReceiver接收到事件
   * InputEventReceiver将回调事件一步步传递给Activity来进行分发
   * Activity先将事件交给DecorView来进行处理,如果DecorView消耗则返回true,否则自己回调onTouchEvent方法



   以上!

你可能感兴趣的:(从你触摸屏幕开始分析android触摸事件分发)