final class SyntheticInputStage extends InputStage
final class NativePostImeInputStage extends AsyncInputStage
implements InputQueue.FinishedInputEventCallback
final class ViewPostImeInputStage extends InputStage
/** \frameworks\base\core\java\android\view\ViewRootImpl.java **/
abstract class InputStage {
private final InputStage mNext;
protected static final int FORWARD = 0;
protected static final int FINISH_HANDLED = 1;
protected static final int FINISH_NOT_HANDLED = 2;
/**
* Creates an input stage.
* @param next The next stage to which events should be forwarded.
*/
public InputStage(InputStage next) {
mNext = next;
}
/**
* 处理event
*/
public final void deliver(QueuedInputEvent q) {
// 有效的event传递给下一stage
if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
forward(q);
} else if (shouldDropInputEvent(q)) { // 应当被drop的Event
finish(q, false);
} else {
apply(q, onProcess(q));
}
}
/**
* 标记该event为finished,并传递给下一个stage
*/
protected void finish(QueuedInputEvent q, boolean handled) {
q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
if (handled) {
q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
}
forward(q);
}
/**
* 将event向前传递给下一个stage
*/
protected void forward(QueuedInputEvent q) {
onDeliverToNext(q);
}
/**
* 根据result code处理对应的event
* Applies a result code from {@link #onProcess} to the specified event.
*/
protected void apply(QueuedInputEvent q, int result) {
if (result == FORWARD) {
forward(q);
} else if (result == FINISH_HANDLED) {
finish(q, true);
} else if (result == FINISH_NOT_HANDLED) {
finish(q, false);
} else {
throw new IllegalArgumentException("Invalid result: " + result);
}
}
/**
* 一般继承类会Override该函数
* Called when an event is ready to be processed.
* @return A result code indicating how the event was handled.
*/
protected int onProcess(QueuedInputEvent q) {
return FORWARD;
}
/**
* 将event传递给下一stage
*/
protected void onDeliverToNext(QueuedInputEvent q) {
if (DEBUG_INPUT_STAGES) {
Log.v(TAG, "Done with " + getClass().getSimpleName() + ". " + q);
}
if (mNext != null) {
mNext.deliver(q);
} else {
// 调用ViewRootImpl的方法
finishInputEvent(q);
}
}
// 判断是否应该丢弃该Event
protected boolean shouldDropInputEvent(QueuedInputEvent q) {
if (mView == null || !mAdded) {
Slog.w(TAG, "Dropping event due to root view being removed: " + q.mEvent);
return true;
} else if ((!mAttachInfo.mHasWindowFocus || mStopped)
&& !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
// 这里是一个focus事件,但当前该window已经不持有input focus,或者已经stopped.
// 该情况可能是该event来自于previous stage,但与此同时该window失去了焦点或者已经被停止
if (isTerminalInputEvent(q.mEvent)) {
// Don't drop terminal input events, however mark them as canceled.
q.mEvent.cancel();
Slog.w(TAG, "Cancelling event due to no window focus: " + q.mEvent);
return false;
}
// Drop non-terminal input events.
Slog.w(TAG, "Dropping event due to no window focus: " + q.mEvent);
return true;
}
return false;
}
void dump(String prefix, PrintWriter writer) {
if (mNext != null) {
mNext.dump(prefix, writer);
}
}
}
来重点看一下其继承类ViewPostInmInputStage:
1)ViewPostImeInputStage#onProgress:
/** \frameworks\base\core\java\android\view\ViewRootImpl.java **/
@Override
protected int onProcess(QueuedInputEvent q) {
if (q.mEvent instanceof KeyEvent) { // 如果是按键事件,processKeyEvent进行处理
return processKeyEvent(q);
} else {
// If delivering a new non-key event, make sure the window is
// now allowed to start updating.
handleDispatchDoneAnimating();
final int source = q.mEvent.getSource();
// 通过source即事件源来分类型进行处理
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
return processPointerEvent(q);
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
return processTrackballEvent(q);
} else {
return processGenericMotionEvent(q);
}
}
}
当判断是 SOURCE_CLASS_POINTER类型的事件后,会调用processPointerEvent方法进行处理。
2)ViewPostImeInputStage#processPointEvent:
/** \frameworks\base\core\java\android\view\View.java **/
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
mAttachInfo.mUnbufferedDispatchRequested = false;
// 此时ViewRootImpl会将事件的处理权移交给View树的根节点,调用dispatchPointerEvent函数
boolean handled = mView.dispatchPointerEvent(event);
if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
mUnbufferedInputDispatch = true;
if (mConsumeBatchedInputScheduled) {
scheduleConsumeBatchedInputImmediately();
}
}
return handled ? FINISH_HANDLED : FORWARD;
}
ViewRootImpl负责将Event事件传递进来,并根据source的不同进行分类处理;进而将事件的控制权与处理权移交给View树的根View进行dispatchPointerEvent进行处理。
3)View#dispatchPointerEvent:
/** \frameworks\base\core\java\android\view\View.java **/
public final boolean dispatchPointerEvent(MotionEvent event) {
// 按照是否是TouchEvent进行分别处理
if (event.isTouchEvent()) {
return dispatchTouchEvent(event);
} else { // 如果不是调用GenericMotionEvent(Generic——一般的)
return dispatchGenericMotionEvent(event);
}
}
/** \frameworks\base\core\java\android\view\View.java **/
public boolean dispatchTouchEvent(MotionEvent event) {
......
// 根据安全策略对Touch Event进行过滤
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
// ListenerInfo中注册了众多的Listener
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
// 可以看到这里会首先调用TouchListener中的onTouch进行事件处理
result = true;
}
// 如果TouchListener中的onTouch返回结果为false的话,View中的onTouchEvent才会继续调用
if (!result && onTouchEvent(event)) {
result = true;
}
}
......
return result;
}
从上面可以看到onTouch与onTouchEvent之间的区别:
1>onTouch方法:
onTouch方法是View的 OnTouchListener借口中定义的方法。
当一个View绑定了OnTouchLister后,当有touch事件触发时,就会调用onTouch方法。
(当把手放到View上后,onTouch方法被一遍一遍地被调用)
2>onTouchEvent方法:
onTouchEvent方法是override 的Activity的方法。
重新了Activity的onTouchEvent方法后,当屏幕有touch事件时,此方法就会别调用。
(当把手放到Activity上时,onTouchEvent方法就会一遍一遍地被调用)
View 中存在onTouchEvent方法,在定义View的时候重写onTouchEvent可以进行事件处理。
3>touch事件的传递:
在一个Activity里面放一个TextView的实例tv,并且这个tv的属性设定为 fill_parent
在这种情况下,当手放到屏幕上的时候,首先会是tv响应touch事件,执行onTouch方法。
如果onTouch返回值为true,
表示这个touch事件被onTouch方法处理完毕,不会把touch事件再传递给Activity,
也就是说onTouchEvent方法不会被调用。
(当把手放到屏幕上后,onTouch方法被一遍一遍地被调用)
如果onTouch的返回值是false,
表示这个touch事件没有被tv完全处理,onTouch返回以后,touch事件被传递给Activity,
onTouchEvent方法被调用。
来看一下上面涉及到的几个简单的类:
1>Listener的综合管理类:
/** \frameworks\base\core\java\android\view\View.java **/
static class ListenerInfo {
/**
* Listener used to dispatch focus change events.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
protected OnFocusChangeListener mOnFocusChangeListener;
/**
* Listeners for layout change events.
*/
private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
protected OnScrollChangeListener mOnScrollChangeListener;
/**
* Listeners for attach events.
*/
private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
/**
* Listener used to dispatch click events.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
public OnClickListener mOnClickListener;
/**
* Listener used to dispatch long click events.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
protected OnLongClickListener mOnLongClickListener;
/**
* Listener used to build the context menu.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
protected OnCreateContextMenuListener mOnCreateContextMenuListener;
private OnKeyListener mOnKeyListener;
private OnTouchListener mOnTouchListener;
private OnHoverListener mOnHoverListener;
private OnGenericMotionListener mOnGenericMotionListener;
private OnDragListener mOnDragListener;
private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
}
可以设想到平时所用到的setOnClickListener等设置Listener的方法,就是将ListenerInfo中管理的相关Listener进行初始化。
/** \frameworks\base\core\java\android\view\View.java **/
public void setOnClickListener(OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}
ListenerInfo getListenerInfo() {
if (mListenerInfo != null) {
return mListenerInfo;
}
mListenerInfo = new ListenerInfo();
return mListenerInfo;
}
验证了前面的设想。
/** \frameworks\base\core\java\android\view\View.java **/
/**
* Interface definition for a callback to be invoked when a touch event is
* dispatched to this view. The callback will be invoked before the touch
* event is given to the view.
*/
public interface OnTouchListener {
/**
* Called when a touch event is dispatched to a view. This allows listeners to
* get a chance to respond before the target view.
*
* @param v The view the touch event has been dispatched to.
* @param event The MotionEvent object containing full information about
* the event.
* @return True if the listener has consumed the event, false otherwise.
*/
boolean onTouch(View v, MotionEvent event);
}
当Acitivity implements OnTouchListner接口时,应当重写该方法;当有Touch Event事件传递进来时,该函数会被首先调用;如果重写的方法返回值为true,onTouchEvent方法将不会被调用;
/** \frameworks\base\core\java\android\view\View.java **/
public boolean onTouchEvent(MotionEvent event) {
// 获得触摸点的位置
final float x = event.getX();
final float y = event.getY();
final int viewFlags = mViewFlags;
if ((viewFlags & ENABLED_MASK) == DISABLED) {
if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
setPressed(false);
}
// 当一个View处于disabled状态时,他仍然会消耗该event事件,但是并不会做出任何响应
return (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
}
if (mTouchDelegate != null) {
if (mTouchDelegate.onTouchEvent(event)) {
return true;
}
}
// 如果View是CLICKABLE或者LONG_CLICKABLE的,继续对event进行处理
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
// TouchEvent分为多种类型:ACTION_UP、ACTION_DOWN、ACTION_CANCEL、ACTION_MOVE,对其进行分别响应处理
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
......
break;
case MotionEvent.ACTION_DOWN:
......
break;
case MotionEvent.ACTION_CANCEL:
......
break;
case MotionEvent.ACTION_MOVE:
......
break;
}
return true;
}
return false;
}
下面分别对其进行分析:
/** \frameworks\base\core\java\android\view\View.java
View#onTouchEvent**/
case MotionEvent.ACTION_DOWN:
// 长按事件标志
mHasPerformedLongPress = false;
if (performButtonActionOnTouchDown(event)) {
break;
}
// 判断touch事件是否是在一个scrolling container中.
boolean isInScrollingContainer = isInScrollingContainer();
// For views inside a scrolling container, delay the pressed feedback for
// a short period in case this is a scroll.
if (isInScrollingContainer) {
mPrivateFlags |= PFLAG_PREPRESSED;
if (mPendingCheckForTap == null) {
mPendingCheckForTap = new CheckForTap();
}
mPendingCheckForTap.x = event.getX();
mPendingCheckForTap.y = event.getY();
postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
} else {
/** 普通touch事件,进行标志设置 **/
// 设置pressed状态
setPressed(true, x, y);
// 判断是否是LongClick事件
checkForLongClick(0);
}
break;
监听到ACTION_DOWN事件,首先后判断是否是在一个Scroller中进行分别处理;如果是普通的Touch事件,会调用serPressed来设置Press状态,同时会根据需要对Touch区域进行重新绘制(比如Button按下的效果);checkForLongClick用来判断是否是长按事件。
/** \frameworks\base\core\java\android\view\View.java **/
private void setPressed(boolean pressed, float x, float y) {
if (pressed) {
drawableHotspotChanged(x, y);
}
setPressed(pressed);
}
public void setPressed(boolean pressed) {
final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
if (pressed) {
mPrivateFlags |= PFLAG_PRESSED;
} else {
mPrivateFlags &= ~PFLAG_PRESSED;
}
// 根据是否需要进行重新UI绘制,绘制函数即为refreshDrawableState
if (needsRefresh) {
refreshDrawableState();
}
dispatchSetPressed(pressed);
}
setPressed方法主要是设置相关的Pressed标志,并在如果需要重新绘制界面时调用refreshDrawableState进行界面绘制。
/** \frameworks\base\core\java\android\view\View.java **/
/** 判断是否是LongClick事件 **/
private void checkForLongClick(int delayOffset) {
if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
mHasPerformedLongPress = false;
if (mPendingCheckForLongPress == null) {
mPendingCheckForLongPress = new CheckForLongPress();
}
mPendingCheckForLongPress.rememberWindowAttachCount();
// 在事件发生规定时间(即定义为Long Click的最短长按时间)后,Post一个判断是否是Long Click的Runnable
// 如果是Long Click事件,该Runnable会进行相应的处理;
// 在后面将会看到,如果TIME_OUT之前有ACTION_UP或者ACTION_MOVE事件发生,则会调用removeLongPressCallback();移除这个Runnable
postDelayed(mPendingCheckForLongPress,
ViewConfiguration.getLongPressTimeout() - delayOffset);
}
}
private CheckForLongPress mPendingCheckForLongPress;
/** 判断是否是Long Click事件的线程 **/
private final class CheckForLongPress implements Runnable {
private intmOriginalWindowAttachCount;
@Override
public void run() {
// 判断是否仍处于Pressed状态
if (isPressed() && (mParent != null)
&& mOriginalWindowAttachCount == mWindowAttachCount) {
// 表明当前是Long Click事件,对其进行Long Click响应
if (performLongClick()) {
mHasPerformedLongPress = true;
}
}
}
public void rememberWindowAttachCount() {
mOriginalWindowAttachCount = mWindowAttachCount;
}
}
/** Long Click事件响应函数 **/
public boolean performLongClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
// 通过调用OnLongClickListener进行响应
boolean handled = false;
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnLongClickListener != null) {
handled = li.mOnLongClickListener.onLongClick(View.this);
}
if (!handled) {
handled = showContextMenu();
}
if (handled) {
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
return handled;
}
case MotionEvent.ACTION_MOVE:
/** @Value获得触摸点的位置,注:每个移动都会源源不断地产生很多ACTION_MOVE事件
* final float x = event.getX();
final float y = event.getY();*/
drawableHotspotChanged(x, y);
// 用以判断当前收拾是否已经超出了该View的范围
if (!pointInView(x, y, mTouchSlop)) {
// 如果超出了View的范围,则撤销ACTION_DOWN中的所有设置
removeTapCallback();
if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
// 撤销Long Click状态
removeLongPressCallback();
// 撤销Click状态
setPressed(false);
}
}
break;
case MotionEvent.ACTION_UP:
// 判断是否是pressed状态
boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
// take focus if we don't have it already and we should in
// touch mode.
boolean focusTaken = false;
if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
focusTaken = requestFocus();
}
if (prepressed) {
setPressed(true, x, y);
}
/** 如果是Long Click,这里就不会产生Click **/
if (!mHasPerformedLongPress) { // 非Long Click状态
// 撤销Long Click的Runnable线程
removeLongPressCallback();
/** 只有处于pressed状态,才会进行click操作 **/
if (!focusTaken) {
// Use a Runnable and post this rather than calling
// performClick directly. This lets other visual state
// of the view update before click actions start.
// 创建一个PerformClick(Runnable),该Runnable的run函数主体就是performClick
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
// 将该线程post,如果post不成功,直接执行官performClick
// 可以看到performClick并不会立即执行,而是添加到队列中,等待前面执行完毕,才会执行
if (!post(mPerformClick)) {
performClick();
}
}
}
/** PressedStateDuration时间之后撤销PressedState状态 **/
if (mUnsetPressedState == null) {
mUnsetPressedState = new UnsetPressedState();
}
if (prepressed) {
postDelayed(mUnsetPressedState,
ViewConfiguration.getPressedStateDuration());
} elseif (!post(mUnsetPressedState)) {
// If the post failed, unpress right now
mUnsetPressedState.run();
}
removeTapCallback();
}
break;
case MotionEvent.ACTION_CANCEL:
setPressed(false);
removeTapCallback();
removeLongPressCallback();
break;
/** @path: \frameworks\base\services\java\com\android\server\SystemServer.java */
class ServerThread extends Thread {
@Override
public void run() {
// 可以看到IMS和WMS是紧密相关的
......
// @value InputManagerService inputManager
inputManager = new InputManagerService(context, wmHandler);
Slog.i(TAG, "Window Manager");
// @value WindowManagerService wm
wm = WindowManagerService.main(context, power, display, inputManager,
uiHandler, wmHandler,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
ActivityManagerService.self().setWindowManager(wm);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
.....
}
}
4、InputMangerService:
/** \frameworks\base\services\core\java\com\android\server\input\InputManagerService.java **/
public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor {
// 指向native端IMS类对象的地址
private final long mPtr;
public InputManagerService(Context context) {
this.mContext = context;
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mUseDevInputEventForAudioJack = context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
// 创建native IMS对象
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
}
可以看到Java层的IMS实际上只是对Native层的InputManager的一层包装;其创建主要是native层进行创建。
/** \frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp **/
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface,
public virtual PointerControllerPolicyInterface
static jlong nativeInit(JNIEnv* env, jclass clazz,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
// 创建一个Message Queue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// 可以看到NativeInputManager中包含有一个Looper,用以进行事件分派
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
// 返回创建的IMS实例对象的地址(强制转化为long类型)
return reinterpret_cast<jlong>(im);
}
创建完实例后,进一步调用start函数,来看一下start函数所完成的功用。
/** \frameworks\base\services\core\java\com\android\server\input\InputManagerService.java **/
public void start() {
......
nativeStart(mPtr);
......
}
private static native void nativeStart(long ptr);
可以看到start仅是对nativeStart本地方法进行封装。
/** \frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp **/
static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) {
// ptr为创建的IMS实例的地址,这里将其强制转化成为NativeInputManager类
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
// 这里进一步调用InputManager的star方法
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
// @value sp<InputManager> mInputManager;
inline sp<InputManager> getInputManager() const { return mInputManager; }
可以看到这里进一步调用了InputManager的start方法;IMS在Native层的主要实现实体其实是InputManager。
/** \frameworks\native\services\inputflinger\InputManager.cpp **/
class InputManagerInterface : public virtual RefBase {
private:
sp<InputReaderInterface> mReader;
sp<InputReaderThread> mReaderThread;
sp<InputDispatcherInterface> mDispatcher;
sp<InputDispatcherThread> mDispatcherThread;
// 构造函数
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
/*** 进行初始化 **/
void InputManager::initialize() {
// 创建两个Thread的实例
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
// start函数
status_t InputManager::start() {
// 可以看到这里会开启两个线程mDispatcherThread,与mReaderThread
// 分别对应InputReaderThread,InputDispatcherThread
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
......
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
if (result) {
mDispatcherThread->requestExit();
return result;
}
return OK;
}
};
可以看到 start函数中开启了两个native端的线程:InputReaderThread和InputDispatcherThread;从名称可以简单推断出前者用以读取Input事件,后者用以对事件进行处理分发。
<一> InputReaderThread:
1、InputReaderThread类:
/** \frameworks\native\services\inputflinger\InputReader.h **/
/** 无限循环从event hub中读取event,然后读取processes他们 */
class InputReaderThread : public Thread {
public:
InputReaderThread(const sp<InputReaderInterface>& reader);
virtual ~InputReaderThread();
private:
sp<InputReaderInterface> mReader;
/** 继承Thread的子类必须实现该函数,因为这个其实是Thread的真正执行函数 **/
// Derived class must implement threadLoop(). The thread starts its life
// here. There are two ways of using the Thread object:
// 1) loop: if threadLoop() returns true, it will be called again if
// requestExit() wasn't called.
// 2) once: if threadLoop() returns false, the thread will exit upon return.
virtual bool threadLoop();
};
/** \frameworks\native\services\inputflinger\InputReader.cpp **/
InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
Thread(/*canCallJava*/true), mReader(reader) {
// 这里初始化重要变量sp<InputReaderInterface> mReader
}
bool InputReaderThread::threadLoop() {
// 调用mReader中的loopOnce函数,可以看出InputReaderInterface是该类的核心
mReader->loopOnce();
return true;
}
可以看到InputReaderThread类的最重要实现在于InputReaderInterface,该类为核心(其运行时类型为InputReader);
/** \frameworks\native\services\inputflinger\InputReader.h **/
class InputReaderInterface : public virtual RefBase
class InputReader : public InputReaderInterface
/** \frameworks\native\services\inputflinger\InputReader.cpp **/
// loopOnce即事件处理函数
void InputReader::loopOnce() {
......
// 其实是通过mEventHub来获取Events的
// @value sp<EventHubInterface> mEventHub;
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
......
// @value sp<QueuedInputListener> mQueuedListener;
mQueuedListener->flush();
}
EventHubInterface定义在EventHub.h中,其getEvents是通过读取/dev/input/下的相关文件来判断是否有新事件,进而通给值InputReader
/** \frameworks\native\services\inputflinger\InputDispatcher.h **/
class InputDispatcherThread : public Thread {
public:
explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
~InputDispatcherThread();
private:
virtual boolthreadLoop();
sp<InputDispatcherInterface> mDispatcher;
};
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
2、InputDispatcher定义:
/** \frameworks\native\services\inputflinger\InputDispatcher.h **/
class InputDispatcher : public InputDispatcherInterface
class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface
可以看到
InputDispatcherInterface
最终继承一个
InputListenerInterface
类;该类明显是一个Listener
/** \frameworks\native\services\inputflinger\InputManager.cpp **/
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
// 这里初始化InputReader时就将InputReader与InputDispatcher建立起了关联
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
可以看到这里最开始就将InputDispatcher与InputReader建立起关联;接下来看InputReader的构造函数,看两者是怎样建立起关联的:
/** \frameworks\native\services\inputflinger\InputReader.cpp **/
InputReader::InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener) :
mContext(this), mEventHub(eventHub), mPolicy(policy),
mGlobalMetaState(0), mGeneration(1),
mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
// 这里将mDispatcher当做InputListenerInterface类型,初始化QueueInputListener
mQueuedListener = new QueuedInputListener(listener);
{ // acquire lock
AutoMutex _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
而上面2中提到InputDispatcher继承了InputListenerInterface,这里可以看到InputReader使用mDispatcher来初始化mQueueListener(QueueInputListener类);
/** \frameworks\native\services\inputflinger\InputListener.h **/
class QueuedInputListener : public InputListenerInterface {
protected:
virtual ~QueuedInputListener();
public:
QueuedInputListener(const sp<InputListenerInterface>& innerListener);
virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
virtual void notifyKey(const NotifyKeyArgs* args);
virtual void notifyMotion(const NotifyMotionArgs* args);
virtual void notifySwitch(const NotifySwitchArgs* args);
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
void flush();
private:
sp<InputListenerInterface> mInnerListener;// mInnerListner即是InputDispatcher
Vector<NotifyArgs*> mArgsQueue; // 后面flush函数中将会用到
};
可以看到这里可以向InputReader注册监听很多事件。
/** \frameworks\native\services\inputflinger\InputListener.cpp **/
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
// 调用NotifyArgs。notify函数
args->notify(mInnerListener);
delete args;
}
mArgsQueue.clear();
}
// 这里仅是一个封装函数,最终调用InputListenerInterface的notifyKey函数
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyKey(this);
}
最终调用InputListenerInterface(即InputDispatcher)的notifyKey回调函数;
/** \frameworks\native\services\inputflinger\InputDispatcher.cpp **/
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
if (!validateKeyEvent(args->action)) { // 判断event是否合法
return;
}
......
// 初始化KeyEvent
KeyEvent event;
event.initialize(args->deviceId, args->source, args->action,
flags, keyCode, args->scanCode, metaState, 0,
args->downTime, args->eventTime);
{ // acquire lock
mLock.lock();
......
KeyEntry* newEntry = new KeyEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, flags, keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
// 继续调用enqueueInboundEventLocked函数
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
}
/** \frameworks\native\services\inputflinger\InputDispatcher.cpp **/
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
// @value Queue<EventEntry> mInboundQueue;
bool needWake = mInboundQueue.isEmpty();
// 将entry入队列
mInboundQueue.enqueueAtTail(entry);
switch (entry->type) { // 如前面所述,InputEvent分为KeyEvent和MotionEvent进行分别处理
case EventEntry::TYPE_KEY: ......
case EventEntry::TYPE_MOTION: .....
}
return needWake;
}
当InputReader读取到一个event之后,最终enqueue进mInboundQueue消息队列中;接下来看怎么处理;
/** \frameworks\native\services\inputflinger\InputDispatcher.cpp **/
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
// 在没有等待的commands事运行一个dispatch loop,这个loop之后可能enqueue commands
if (!haveCommandsLocked()) {
dispatchOnceInnerLocked(&nextWakeupTime);
}
// 如果有等待的commands的话,就运行所有的commands
// If any commands were run then force the next poll to wake up immediately.
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
// Wait for callback or timeout or wake. (make sure we round up, not down)
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);
}
继续来看dispatchOnceInnerLocked函数;
/** \frameworks\native\services\inputflinger\InputDispatcher.cpp **/
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
.......
// 根据mPendingEvent的Type的不同分别进行处理
switch (mPendingEvent->type) {
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
......
done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
break;
}
case EventEntry::TYPE_DEVICE_RESET: {
......
done = dispatchDeviceResetLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
break;
}
// KeyEvent采用dispatchKeyLocked进行处理
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
......
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
// MotionEvent采用dispatchMotionLocked进行处理
case EventEntry::TYPE_MOTION: {
......
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
}
default:
ALOG_ASSERT(false);
break;
}
}
针对Event的type的不同进行不同的处理,KeyEvent采用dispatchKeyLocked进行处理,MotionEvent采用dispatchMotionLocked进行处理;下面以KeyEvent为例进行分析,下面忽略对event的具体处理细节,具体来看事件是如何传递的;
/** \frameworks\native\services\inputflinger\InputDispatcher.cpp **/
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
......
/** 确定事件的接收方(Target) **/
Vector<InputTarget> inputTargets;
int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
setInjectionResultLocked(entry, injectionResult);
addMonitoringTargetsLocked(inputTargets);
/** 将消息dispatch给Target **/
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
前面对event的处理忽略掉,重点来看系统是如何查找event对应的接收方(Target)的,接下来分析函数findFocusedWindowTargetsLocked;
/** \frameworks\native\services\inputflinger\InputDispatcher.cpp **/
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
int32_t injectionResult;
String8 reason;
// mFocusedWindowHandle表示当前焦点窗口的句柄
// @value sp<InputWindowHandle> mFocusedWindowHandle;
/** 当获得焦点的窗口为null时,会丢弃这一事件 **/
if (mFocusedWindowHandle == NULL) {
if (mFocusedApplicationHandle != NULL) {
// 如果没有焦点窗口,但焦点窗口所在的应用程序进程存在,说明该应程序还在启动过程中,故等待nextWakeupTime后再重试
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
mFocusedApplicationHandle, NULL, nextWakeupTime,
"Waiting because no window has focus but there is a "
"focused application that may eventually add a window "
"when it finishes starting up.");
goto Unresponsive;
}
injectionResult = INPUT_EVENT_INJECTION_FAILED;
goto Failed;
}
/** 如果执行到这里说明当前有焦点窗口 **/
// 先判断权限
if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
goto Failed;
}
// 如果当前焦点窗口正在处理上一个事件,采取和最上面一样的作法,等待一段时间后重试
reason = checkWindowReadyForMoreInputLocked(currentTime,
mFocusedWindowHandle, entry, "focused");
if (!reason.isEmpty()) {
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.string());
goto Unresponsive;
}
// 成功找到匹配的窗口,通过addWindowTargetLocked添加到inputTargets变量中
injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
addWindowTargetLocked(mFocusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
inputTargets);
Failed:
Unresponsive:
nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
updateDispatchStatisticsLocked(currentTime, entry,
injectionResult, timeSpentWaitingForApplication);
return injectionResult;
}
上面获取到目标窗口的流程较为清晰简单,其主要的变量是mFocusedWindowHandle,它表示焦点窗口的句柄,而InputDispatcher又是如何获取到它的。
/** \frameworks\base\services\core\java\com\android\server\wm\InputMonitor.java **/
/* Updates the cached window information provided to the input dispatcher. */
public void updateInputWindowsLw(boolean force) {
......
// Send windows to native code.
// @value private final WindowManagerService mService;
// @value final InputManagerService mInputManager;
mService.mInputManager.setInputWindows(mInputWindowHandles);
......
}
/** \frameworks\base\services\core\java\com\android\server\input\InputManagerService.java **/
public void setInputWindows(InputWindowHandle[] windowHandles) {
nativeSetInputWindows(mPtr, windowHandles);
}
private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
/** \frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp **/
static void nativeSetInputWindows(JNIEnv* env, jclass clazz,
jlong ptr, jobjectArray windowHandleObjArray) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
im->setInputWindows(env, windowHandleObjArray);
}
/*-----NativeInputManager-----*/
void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
Vector<sp<InputWindowHandle> > windowHandles;
......
// @value sp<InputManager> mInputManager;
mInputManager->getDispatcher()->setInputWindows(windowHandles);
......
}
/** \frameworks\native\services\inputflinger\InputManager.cpp **/
sp<InputDispatcherInterface> InputManager::getDispatcher() {
return mDispatcher;
}
/** \frameworks\native\services\inputflinger\InputDispatcher.cpp **/
void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
{ // acquire lock
AutoMutex _l(mLock);
Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
mWindowHandles = inputWindowHandles;
sp<InputWindowHandle> newFocusedWindowHandle;
......
// 一系列处理
mFocusedWindowHandle = newFocusedWindowHandle;
.....
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
mLooper->wake();
}
可以看到这里涉及到了InputMonitor、WMS与IMS之间的交互;
/** \frameworks\native\services\inputflinger\InputDispatcher.h **/
/*
* An input target specifies how an input event is to be dispatched to a particular window
* including the window's input channel, control flags, a timeout, and an X / Y offset to
* be added to input event coordinates to compensate for the absolute position of the
* window area.
*/
structInputTarget {
enum { // 该枚举类列举个关于目标窗口的各种属性值描述
/* This flag indicates that the event is being delivered to a foreground application. */
FLAG_FOREGROUND = 1 << 0, // 说明目标窗口是前台应用
......
}
/** InputDispatcher与WMS建立关联通信的地方 */
sp<InputChannel> inputChannel;
};
这里引出了重要的类InputChannel,InputDispatcher与WMS也是跨进程通信的,其通过InputChannel进行通信。
1、InputChannel:
/** \frameworks\native\include\input\InputTransport.h **/
/*
* An input channel consists of a local unix domain socket used to send and receive
* input messages across processes. Each channel has a descriptive name for debugging purposes.
*
* Each endpoint has its own InputChannel object that specifies its file descriptor.
*
* The input channel is closed when all references to it are released.
*/
// 上面提到InputChannel是使用unix domain socket(UDS)进行通信的,而非Binder
class InputChannel : public RefBase {
protected:
virtual~InputChannel();
public:
InputChannel(const String8& name, int fd); // fd类似设备描述符
// 用于打开一个InputChannel对(Pair),用以实现双向通信
static status_t openInputChannelPair(const String8& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);
inline String8 getName() const { returnmName; }
inlineint getFd() const { returnmFd; }
// 发送接收信息
status_t sendMessage(const InputMessage* msg);
status_t receiveMessage(InputMessage* msg);
/* Returns a new object that has a duplicate of this channel's fd. */
sp<InputChannel> dup() const;
private:
String8 mName;
int mFd; // 重点要弄清该变量代表的含义
};
上面提到InputChannel是使用UDS进行通信的,Android系统中最为常用的进程间通信时Binder通信,其次便是UDS进行单机内的进程间通信,也称IPC Socket。下面进行验证。
/** \frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java **/
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel) {
......
if (outInputChannel != null && (attrs.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
// 设置当前的通道名
String name = win.makeInputChannelName();
// 打开一对InputChannel通道
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
win.setInputChannel(inputChannels[0]);
inputChannels[1].transferTo(outInputChannel);
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
}
......
}
/** \frameworks\base\core\java\android\view\InputChannel.java **/
public static InputChannel[] openInputChannelPair(String name) {
if (name == null) {
throw new IllegalArgumentException("name must not be null");
}
return nativeOpenInputChannelPair(name);
}
private static native InputChannel[] nativeOpenInputChannelPair(String name);
4、InputChannel::openInputChannelPair:
/** \frameworks\native\libs\input\InputTransport.cpp **/
status_t InputChannel::openInputChannelPair(const String8& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
// 建立UDS
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
status_t result = -errno;
outServerChannel.clear();
outClientChannel.clear();
return result;
}
// 设置缓冲区大小
int bufferSize = SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
// 创建Server与Client端实例
String8 serverChannelName = name;
serverChannelName.append(" (server)");
outServerChannel = new InputChannel(serverChannelName, sockets[0]);
String8 clientChannelName = name;
clientChannelName.append(" (client)");
outClientChannel = new InputChannel(clientChannelName, sockets[1]);
return OK;
}
这里可以看到IMS与WMS之间是通过InputChannel,使用UDS进行进程间通信的;