前言
Android输入事件的分发主要为按键(KeyEvent)事件和触摸(MotionEvent)事件,事件由ViewRootImp经DecorView层层传递到子控件中,最终由子控件处理的一个过程
KeyEvent事件类型
public static final int ACTION_DOWN = 0;
public static final int ACTION_UP = 1;
public static final int ACTION_MULTIPLE = 2;
MotionEvent事件类型
public static final int ACTION_DOWN = 0;
public static final int ACTION_UP = 1;
public static final int ACTION_MOVE = 2;
public static final int ACTION_CANCEL = 3;
输入事件从WindowInputEventReceiver到DecorView的整个流程如下:
Activity::attach
ActivityManagerService回调ActivityThread的performLaunchActivity,和Activity的onCreate函数对应。performLaunchActivity函数会去创建新的Activity,并且调用activity的attach函数来对初始化mWindow,设置Window回调函数为当前Activity
// step 1, 创建PhoneWindow对象
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
// step 2 , 设置回调函数为当前Activity
mWindow.setCallback(this);
Activity::makeVisible
ActivityManagerService回调ActivityThread的performResumeActivity,和Activity的onResume函数对应。performResumeActivity函数将Activity中的mDecor添加到WindowManagerGlobal中并添加相对应的Window到WindowManagerService中,然后将mDecor设置为可见状态,此时的Activity界面就能显示出来了
void makeVisible() {
// step 1, getWindowManager()对象为WindowManagerImpl对象
ViewManager wm = getWindowManager();
// step 2, wm.addView最终调用的是WindowManagerGlobal的addView函数
wm.addView(mDecor, getWindow().getAttributes());
// step 3, mDecor设置为可见状态
mDecor.setVisibility(View.VISIBLE);
}
WindowManagerGlobal::addView
WindowManagerGlobal设置为单列模式,一个进程中对应一个实列,用来和WindowManagerService之间通信, WindowManagerGlobal有几个比较重要的成员变量sWindowSession, mViews,mRoots,mParams
// 用来和WindowManagerService之间通信
private static IWindowSession sWindowSession;
// 保存Activity的根View
private final ArrayList<View> mViews = new ArrayList<View>();
// 一个窗口对应一个ViewRootImpl
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
// 窗口属性
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
// step 1 , 创建ViewRootImpl对象
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
// step 2 , 将view, mRoots,wparams参数保存在WindowManagerGlobal成员变量中
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// step 3 , 调用ViewRootImpl的setView函数,
root.setView(view, wparams, panelParentView);
}
ViewRootImpl::setView
ViewRootImpl是APK进程和WindowManagerService之间的中转站,根据窗口属性LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL来判断view是否能接收输入事件,如果对应的bit位不为0,则表示能接收输入事件,创建对应的输入通道,mWindowSession将ViewRootImpl中的mWinodw添加到WMS中,把mInputChannel也传进去,他是out参数, WMS创建完socket输入系统关联上后返回给APK端(客服端)
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
// step 1 , 如果窗口能接收事件,则创建InputChannel
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
mInputChannel = new InputChannel();
}
// step 2 , 把mWindow添加到WindowManagerService中
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);
}
// step 3, 创建事件接收者
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
// Set up the input pipeline.
// step 4, 构建事件处理的责任链,处理KeyEvent和MotionEvent事件为ViewPostImeInputStage
CharSequence counterSuffix = attrs.getTitle();
mSyntheticInputStage = new SyntheticInputStage();
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);
mFirstInputStage = nativePreImeStage;
mFirstPostImeInputStage = earlyPostImeStage;
}
}
}
WindowInputEventReceiver
WindowInputEventReceiver是Apk进程中的事件接收者,WindowInputEventReceiver继承InputEventReceiver,当有系统按键派发到APK进程中时,会触发InputEventReceiver的onInputEvent函数
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
@Override
public void onInputEvent(InputEvent event, int displayId) {
// step 1, 最后一个参数为true表示需要立即处理这个事件
enqueueInputEvent(event, this, 0, true);
}
}
ViewRootImpl::enqueueInputEvent
将InputEvent对象封装到QueuedInputEvent中,last不为空,则将event事件添加到队尾,为空,则添加到队列头,先来先处理的原则。onInputEvent中调用的enqueueInputEvent事件,processImmediately为true, 需要马上处理此事件。
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
// step 1, 获取输入事件队列
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
QueuedInputEvent last = mPendingInputEventTail;
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;
mPendingInputEventTail = q;
}
mPendingInputEventCount += 1;
// step 2, 处理输入事件
if (processImmediately) {
doProcessInputEvents();
} else {
// scheduleProcessInputEvents通过handler发送异步消息,最终也是调用doProcessInputEvents
scheduleProcessInputEvents();
}
}
ViewRootImpl::doProcessInputEvents
mPendingInputEventHead指向队列头部,循环遍历QueuedInputEvent链表, 通过deliverInputEvent函数派发输入事件
void doProcessInputEvents() {
// step 1, 派发队列中的输入事件
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
if (mPendingInputEventHead == null) {
mPendingInputEventTail = null;
}
q.mNext = null;
mPendingInputEventCount -= 1;
long eventTime = q.mEvent.getEventTimeNano();
long oldestEventTime = eventTime;
if (q.mEvent instanceof MotionEvent) {
MotionEvent me = (MotionEvent)q.mEvent;
if (me.getHistorySize() > 0) {
oldestEventTime = me.getHistoricalEventTimeNano(0);
}
}
mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
// step 2 , 传递输入事件
deliverInputEvent(q);
}
// step 3, 从handler中移除MSG_PROCESS_INPUT_EVENTS异步消息
if (mProcessInputEventsScheduled) {
mProcessInputEventsScheduled = false;
mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
}
}
ViewRootImpl::deliverInputEvent
InputStage责任链在setView的时候设置
private void deliverInputEvent(QueuedInputEvent q) {
// step 1, 找到对应的责任链
InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
// step 2, 朝着责任链派发事件
if (stage != null) {
stage.deliver(q);
} else {
// step 3, 事件处理完成, 告知系统(InputDispatch线程),派发下一个输入事件
finishInputEvent(q);
}
}
InputStage::deliver
如果q.mFlags的QueuedInputEvent.FLAG_FINISHED的bit位不为0,表示事件消费完了,接下来处理下一事件。每个InputStage对象都实现了onProcess函数,返回值为FORWARD,FINISH_HANDLED,FINISH_NOT_HANDLED, 如果返回FORWARD表示事件需要沿责任链往下传,FINISH_HANDLED或FINISH_NOT_HANDLED则finish当前事件,派发结束
public final void deliver(QueuedInputEvent q) {
if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
// step 1, 派发下一个事件
forward(q);
} else if (shouldDropInputEvent(q)) {
// step 2, 事件处理完成, 结束事件
finish(q, false);
} else {
// step 3, onProcess函数对事件的处理
// apply根据此事件是否消费,是否需要继续往下流转
apply(q, onProcess(q));
}
}
InputStage::apply
protected void apply(QueuedInputEvent q, int result) {
if (result == FORWARD) {
// step 1, 派发下一个事件
forward(q);
} else if (result == FINISH_HANDLED) {
// step 2, 结束事件
finish(q, true);
} else if (result == FINISH_NOT_HANDLED) {
// step 3, 结束事件
finish(q, false);
} else {
throw new IllegalArgumentException("Invalid result: " + result);
}
}
InputStage::forward
protected void forward(QueuedInputEvent q) {
// 派发下一个事件
onDeliverToNext(q);
}
ViewPostImeInputStage::onProcess
在没有输入法的情况下,处理按键事件和触摸事件的主要InputStage为ViewPostImeInputStage
protected int ViewPostImeInputStage::onProcess(QueuedInputEvent q) {
if (q.mEvent instanceof KeyEvent) {
// step 1, 处理按键事件
return processKeyEvent(q);
} else {
final int source = q.mEvent.getSource();
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
// step 2, 处理触摸事件
return processPointerEvent(q);
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
return processTrackballEvent(q);
} else {
return processGenericMotionEvent(q);
}
}
}
KeyEvent事件分析
ViewPostImeInputStage::processKeyEvent
mView为DecorView
private int processKeyEvent(QueuedInputEvent q) {
final KeyEvent event = (KeyEvent)q.mEvent;
// step1 , 派发按键事件
if (mView.dispatchKeyEvent(event)) {
return FINISH_HANDLED;
}
return FORWARD;
}
DecorView::dispatchKeyEvent
mWindow.getCallback对象为Activity, 调用actvity的dispatchKeyEvent(event)函数,如果事件被activity消费了, 则返回ture,直接返回了,当Activity没有消费这个按键事件时,则会调用PhoneWindow的onKeyDown或onKeyUp事件
public boolean dispatchKeyEvent(KeyEvent event) {
final int keyCode = event.getKeyCode();
final int action = event.getAction();
final boolean isDown = action == KeyEvent.ACTION_DOWN;
if (!mWindow.isDestroyed()) {
// step 1, Window.Callback为Acitivity对象
final Window.Callback cb = mWindow.getCallback();
final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
: super.dispatchKeyEvent(event);
if (handled) {
return true;
}
}
// step 2, 按键事件没有被activity处理,则将按键交给PhoneWindow的onKeyDown,onKeyUp处理
return isDown ? mWindow.onKeyDown(mFeatureId, event.getKeyCode(), event)
: mWindow.onKeyUp(mFeatureId, event.getKeyCode(), event);
}
Activity::dispatchKeyEvent
首先判断如果是KEYCODE_MENU事件,则交给mActionBar处理, 不是则将事件交给PhoneWindow的superDispatchKeyEvent处理, 最终又回到DecorView中, 如果Window不能处理此事件,最后交由event.dispatch处理, 第一个参数传入为this,最终回调Activity的onKeyDown,onKeyUp来处理按键事件
public boolean dispatchKeyEvent(KeyEvent event) {
// step 1, KEYCODE_MENU事件,如果有mActionBar, 则交给mActionBar处理
final int keyCode = event.getKeyCode();
if (keyCode == KeyEvent.KEYCODE_MENU &&
mActionBar != null && mActionBar.onMenuKeyEvent(event)) {
return true;
}
Window win = getWindow();
// step 2, 将事件交给PhoneWindow的superDispatchKeyEvent处理
if (win.superDispatchKeyEvent(event)) {
return true;
}
View decor = mDecor;
if (decor == null) decor = win.getDecorView();
// step 3, PhoneWindow没有处理KeyEvent事件,则交给event.dispatch处理
// event.dispatch传入this,最终回调Activity的onKeyDown,onKeyUp处理事件
return event.dispatch(this, decor != null
? decor.getKeyDispatcherState() : null, this);
}
public class Activity extends ContextThemeWrapper
implements KeyEvent.Callback {}
PhoneWindow::superDispatchKeyEvent
public boolean superDispatchKeyEvent(KeyEvent event) {
// step 1, 调用DecorView的superDispatchKeyEvent
return mDecor.superDispatchKeyEvent(event);
}
DecorView::superDispatchKeyEvent
DecorView继承FrameLayout,FrameLayout继承ViewGroup,ViewGroup继承View
public boolean superDispatchKeyEvent(KeyEvent event) {
// step 1,调用ViewGroup的superDispatchKeyEvent
return super.dispatchKeyEvent(event);
}
ViewGroup::dispatchKeyEvent
public boolean dispatchKeyEvent(KeyEvent event) {
if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
== (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
// step 1, 调用View的dispatchKeyEvent函数
if (super.dispatchKeyEvent(event)) {
return true;
}
} else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
== PFLAG_HAS_BOUNDS) {
// step 2, 调用mFocused View的dispatchKeyEvent函数
if (mFocused.dispatchKeyEvent(event)) {
return true;
}
}
return false;
}
View::dispatchKeyEvent
public boolean dispatchKeyEvent(KeyEvent event) {
// step 1, 如果View实现了mOnKeyListener,则调用View的mOnKeyListener的onKey函数
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
// 事件消费, 直接返回
return true;
}
// step 2, 事件没有消费完,则调用View自身的onKeyDown,onKeyUp处理事件
if (event.dispatch(this, mAttachInfo != null
? mAttachInfo.mKeyDispatchState : null, this)) {
return true;
}
return false;
}
KeyEvent事件时序图
MotionEvent事件分析
ViewPostImeInputStage::processPointerEvent
private int ViewPostImeInputStage::processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
// 调用DecorView的dispatchPointerEvent
boolean handled = mView.dispatchPointerEvent(event);
return handled ? FINISH_HANDLED : FORWARD;
}
View::dispatchPointerEvent
DecorView和ViewGroup都没有dispatchPointerEvent函数,dispatchPointerEvent函数实现在View中,View中的dispatchPointerEvent函数又调用dispatchTouchEvent函数,ViewGroup中重写父类dispatchTouchEvent函数,dispatchTouchEvent函数最终调用的是ViewGroup中的dispatchTouchEvent函数
public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
// step 1, 派发触摸事件
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}
ViewGroup::dispatchTouchEvent_01
ViewGroup::dispatchPointerEvent函数有点复杂,我们拆开来分析, 如果事件是down事件则清空TouchTartget链表, 重置状态。接下来调用onInterceptTouchEvent函数判断是否要将此事件拦截
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;
// step 1, 如果是down事件,重置状态,触摸事件是以down事件开始
if (actionMasked == MotionEvent.ACTION_DOWN) {
cancelAndClearTouchTargets(ev);
resetTouchState();
}
// step 2,事件是否被拦截,intercepted返回为true表示拦截
// mFirstTouchTarget表示消费down事件的view
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
// step 3, onInterceptTouchEvent是否需要拦截此事件
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
ViewGroup::dispatchTouchEvent_02
人为是不能触发canceled事件的, 触摸事件没有被取消并且没有被拦截的情况下,遍历所有子View或ViewGroup,在子View或ViewGroup区域内的触摸事件交给子对应的View或ViewGroup处理,调用dispatchTransformedTouchEvent函数来做后面的处理
// step 3, 事件没有取消,并且没有被拦截
TouchTarget newTouchTarget = null;
boolean alreadyDispatchedToNewTouchTarget = false;
if (!canceled && !intercepted) {
if (actionMasked == MotionEvent.ACTION_DOWN
|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
final int actionIndex = ev.getActionIndex(); // always 0 for down
// step 4, 遍历ViewGroup中的子View或子ViewGroup
final int childrenCount = mChildrenCount;
if (newTouchTarget == null && childrenCount != 0) {
final float x = ev.getX(actionIndex);
final float y = ev.getY(actionIndex);
final View[] children = mChildren;
for (int i = childrenCount - 1; i >= 0; i--) {
// step 5, 如果能接收触摸事件并且触摸点在对应的子View内,则往下走
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
ev.setTargetAccessibilityFocus(false);
continue;
}
newTouchTarget = getTouchTarget(child);
// step 6, 调用dispatchTransformedTouchEvent来处理触摸事件
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
// step 7, 将当前view添加到TouchTarget链表中
newTouchTarget = addTouchTarget(child, idBitsToAssign);
alreadyDispatchedToNewTouchTarget = true;
break;
}
}
}
}
}
ViewGroup::dispatchTouchEvent_03
最后交给dispatchTransformedTouchEvent函数来做处理
// step 8, 如果没有子View处理down事件,则ViewGroup自己处理
if (mFirstTouchTarget == null) {
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
TouchTarget target = mFirstTouchTarget;
while (target != null) {
final TouchTarget next = target.next;
// step 9, alreadyDispatchedToNewTouchTarget为true表示此触摸事件为down事件,并且已经消费
if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
handled = true;
} else {
// step 10, 派发给对应的target对应的View处理
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
}
}
}
ViewGroup::dispatchTransformedTouchEvent
如果ViewGroup没有子View则自己处理,否则交给子View或子ViewGroup处理,递归处理
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
final boolean handled;
// step 1, 如果没有子View,super则为View, 调用View的dispatchTouchEvent函数
if (child == null) {
handled = super.dispatchTouchEvent(transformedEvent);
} else {
final float offsetX = mScrollX - child.mLeft;
final float offsetY = mScrollY - child.mTop;
transformedEvent.offsetLocation(offsetX, offsetY);
if (!child.hasIdentityMatrix()) {
transformedEvent.transform(child.getInverseMatrix());
}
// step 2, 递归调用View或ViewGroup的dispatchTouchEvent函数
handled = child.dispatchTouchEvent(transformedEvent);
}
return handled;
}
View::dispatchTouchEvent
View的mOnTouchListener处理事件的优先级高于View自己的onTouchEvent
public boolean dispatchTouchEvent(MotionEvent event) {
boolean result = false;
// step 1, event事件带有MotionEvent.FLAG_WINDOW_IS_OBSCURED标记会返回false
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
// step 2, View的mOnTouchListener不为空且view为ENABLE状态
// 则调用mOnTouchListener的onTouch函数来处理MotionEvent事件
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
// step 3, 事件被mOnTouchListener消费
result = true;
}
// step 4, 事件没有被消费, 则调用View的onTouchEvent函数来处理MotionEvent事件
if (!result && onTouchEvent(event)) {
// step 5, 事件被onTouchEvent消费
result = true;
}
}
// 返回事件处理结果
return result;
}
MotionEvent事件时序图
总结
触摸事件的传导流程中,一些重要的函数或监听函数如下: