View机制深入学习(三) View中的消息传递及InputManagerService

以TouchEvent为主,看一下View和ViewGroup内部是如何处理Input Events的;
一、View中TouchEvent的投递过程
    现在版本的Android中、事件处理者已经不由InputEventReceiver来承担,而是通过多种形式的InputStage来进行分别处理。如:
final class SyntheticInputStage extends InputStage
final class NativePostImeInputStage extends AsyncInputStage
      implements InputQueue.FinishedInputEventCallback
final class ViewPostImeInputStage extends InputStage
1、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:

2、ViewPostImeInputStage 

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);
    }
}
    对于TouchEvent,显然是会调用dispatchTouchEvent进行处理的:

4)View#dispatchTouchEvent
/** \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的方法。
重新了ActivityonTouchEvent方法后,当屏幕有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;
}
验证了前面的设想。


2>View#onTouchListener:
/** \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方法将不会被调用;

5)继续来看重要的事件处理方法View#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;
}
下面分别对其进行分析:
1>ACTION_DOWN:
    一般触摸事件的顺序为ACTION_DOWN->ACTION_UP,或者ACTION_DOWN->ACTION_MOVE->ACTION_UP;可以看到ACTION_DOWN是后续事件的起点。
I、事件具体处理函数
/** \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用来判断是否是长按事件。

II.View#setPressed:
/** \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进行界面绘制。

III.View#checkForLongClick:
/** \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;
}

2>ACTION_MOVE:
ACTION_MOVE事件是由于用户按下并拖动的结果,知道产生ACTION_UP或者ACTION_CANCEL事件结束;
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;


3>ACTION_UP:
ACTION_UP是手势的结束点。其处理函数最重要的就是判断是否会产生Click;
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;


4>ACTION_CANCEL:
    ACTION_CANCEL事件并不是由用户主动产生的,而是系统谨慎判断之后的结果,说明当前手势已经被废弃,则接下来执行清理操作。
case MotionEvent.ACTION_CANCEL:
    setPressed(false);
    removeTapCallback();
    removeLongPressCallback();
    break;

二、InputManagerService:
    前面提到了ViewRootImpl对TouchEvent事件的处理流程,那这些事件又是怎么来的。事件的来源可以分为“软件”,“硬件”两种;
主要的事件包含有:
案件事件(KeyEvent)    :即物理按键按下产生的事件,相关的常用物理按键一般有HOME,BACK等
触摸事件(TouchEvent): 
鼠标事件(MouseEvent)、轨迹球事件(TrackBallEvent)(这两个已经不常见);

针对所有事件的共性抽象出了InputEvent接口;其有两个子类:KeyEvent,MotionEvent;

1、事件的投递流程

1>源信息采集
    对“硬件源”产生的原始信息进行收集;它需要Linux内核驱动的支持,Android系统通过/dev/input下的节点来访问当前发生的事件。
2>前期处理
    对收集到信息进行筛选以及格式转化
3>WMS分配
    WMS是窗口的Manager,同时也是InputEvent的派发者。
4>应用程序处理

2、InputManagerService启动:
    InputManagerService同样也是有SystemServer进程启动,这个在Android启动过程——init.rc,Zygote,SystemServer中已经提到过:
/** @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层进行创建。


5、native层的InputManagerService——NativeInputManager类
/** \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函数所完成的功用。

3、InputManagerService#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本地方法进行封装。

4、NativeInputManager#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。

5、InputManager#start
/** \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();
};


2、InputReaderThread类的具体实现
/** \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);

3、InputReaderInterface:
/** \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

<二>InputDispatcherThread:
    同理该线程的实现核心为InputDispatcher类,进行事件的派发和处理。
1、InputDispatcherThread定义
/** \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

3、InputManager构造函数
    回到前面Native层的IMS(InputManager)构造函数:
/** \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的构造函数,看两者是怎样建立起关联的:

4、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类);
这个mQueueListener前面就见到过,在InputReader::loopOnce()事件获取函数中,通过Event Hub获取到event事件,然后调用mQueuedListener->flush();

5、QueueInputListener#flush:
1)先看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注册监听很多事件。

2)flush函数
/** \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回调函数;

    总结前面的流程即InputReaderThread通过EventHub不断读取获取event信息,获得事件后,调用InputDispather的notifyKey函数来通知InputDispathcer进行处理。
其具体的流程:


<三>事件处理流程
1、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
}

2、InputDispatcher::enqueueInboundEventLocked:
/** \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消息队列中;接下来看怎么处理;

前面InputDispatcherThread的运行函数threadLoop,其主体是调用InputDispatcher中的dispatchOnce进行处理,可想而知,消息处理函数自然在dispatchOnce中;

3、InputDispatcher::dispatchOnce:
/** \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函数;

4、InputDispathcer#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的具体处理细节,具体来看事件是如何传递的;

5、InputDispatcher::dispatchKeyLocked:
/** \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

6、InputDispatcher::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又是如何获取到它的。

这里先引出InputMonitor的概念,它是WMS与InputDispatcher的中介;WMS通过InputMonitor的updateInputWindowsLw来告知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之间的交互;

找到了InputTarget,InputDispatcher又是如何与之通信的?

7、InputTarget:

/** \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进行通信。

<四>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。下面进行验证。

2、从源头开看InputChannel的创建初始化
/** \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);
    }
    ......
}

3、InputChannel#openInputChannelPair
/** \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进行进程间通信的;

    上面整理的流程可以简单概括为IMS中有两个event时间相关的线程InputReaderThread和InputDispatcherThread;
InputReaderThread通过EventHub读取/dev/input/下是否有新事件产生,然后传递给InputDispatcherThread,该Thread通过InputMonitor与WMS建立关联,确定当前焦点窗口,来选择匹配的InputTarget,进而将该event通过InputChannel传递给对应Target进行处理;接下来分析传递的事件是如何到达ViewRootImpl进行接下来的处理的。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值