首页 > 代码库 > InputMonitor笔记

InputMonitor笔记

文章仅记录自己的一点理解,仅供自己参考。

1、mInputFocus

WMS.addWindow()-->WMS.finishUpdateFocusedWindowAfterAssignLayersLocked()-->InputMonitor.setInputFocusLw()-->mInputFocus = newWindow;

add一个window的时候会重新寻找焦点窗口,并把焦点窗口保存在WMS.mCurrentFocus中,这个焦点窗口也会保存到InputMonitor.mInputFocus 中。关键代码:

<span style="font-size:18px;">addWindow(){
            ……
            boolean focusChanged = false;
            if (win.canReceiveKeys()) {
                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);
                if (focusChanged) {
                    imMayMove = false;
                }
            }

            if (imMayMove) {
                moveInputMethodWindowsIfNeededLocked(false);
            }

            assignLayersLocked(displayContent.getWindowList());
            // Don't do layout here, the window must call
            // relayout to be displayed, so we'll do it there.

            if (focusChanged) {
                finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
            }
            mInputMonitor.updateInputWindowsLw(false /*force*/);
           …………
}
</span>
这几行代码虽短,逻辑也很简单,但是调用了很多方法。对于canReceiveKeys()函数:

    public final boolean canReceiveKeys() {
        return isVisibleOrAdding()
                && (mViewVisibility == View.VISIBLE)
                && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
    }

如果窗口设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE属性,那么该窗口是不能获得焦点的,即canReceiveKeys()会返回false,也就是说焦点窗口是不会更改的。对于悬浮的窗口一般来说是不需要获得焦点的,故一般设置WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE属性,不然会存在一些问题。如果该窗口可以接受key事件(这个key事件有点歧义,并不是只接受按键事件),那么就调用updateFocusedWindowLocked(),这个以后再研究。如果焦点窗口发生变更,那么就调用moveInputMethodWindowsIfNeededLocked(false)来移动输入法窗口到合适的位置。

mInputFocus中保存的窗口在调用InputMonitor.updateInputWindowsLw()时最终设置到InputDispatcher.mFocusedWindowHandle中去了。

2、mInputDispatchFrozen

冻结InputDispatcher标志,“ When true, prevents input dispatch from proceeding until set to false again.”。

①WMS.startFreezingDisplayLocked()-->InputMonitor.freezeInputDispatchingLw()-->mInputDispatchFrozen = true; updateInputDispatchModeLw();

②WMS.stopFreezingDisplayLocked()-->InputMonitor.thawInputDispatchingLw()-->mInputDispatchFrozen = false; updateInputDispatchModeLw();-->InputManagerService.setInputDispatchMode()-->InputDispatcher.setInputDispatchMode(bool enabled, bool frozen)-->mDispatchFrozen = frozen;

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    nsecs_t currentTime = now();

    // Reset the key repeat timer whenever we disallow key events, even if the next event
    // is not a key.  This is to ensure that we abort a key repeat if the device is just coming
    // out of sleep.
    if (!mPolicy->isKeyRepeatEnabled()) {
        resetKeyRepeatLocked();
    }

    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
    if (mDispatchFrozen) {
#if DEBUG_FOCUS
        ALOGD("Dispatch frozen.  Waiting some more.");
#endif
        return;
}
……….
}
调用dispatchOnceInnerLocked()分发事件时,直接return掉。上面的调用逻辑可以知道冻结/解冻显示屏时,会冻结InputDispatcher的分发流程。

3、mInputDispatchEnabled

一个java层控制InputDispatcher的开关。

①WMS.setEventDispatching()-->InputMonitor.setEventDispatchingLw()

②WMS.performEnableScreen()-->InputMonitor.setEventDispatchingLw()-->mInputDispatchEnabled = enabled;updateInputDispatchModeLw();-->InputManagerService.setInputDispatchMode()-->InputDispatcher.setInputDispatchMode(bool enabled, bool frozen)-->mDispatchEnabled = enabled;

具体是怎么使能InputDispatcher的?

 if (!mDispatchEnabled) {
        dropReason = DROP_REASON_DISABLED;
    }
在dispatchOnceInnerLocked()中会设置dropReason(放弃原因),如果dropReason不为0表示输入事件将被放弃掉,不会分发。
google源码是这样解释的:“ When true, input dispatch proceeds normally.  Otherwise all events are dropped. Initially false, so that input does not get dispatched until boot is finished at which point the ActivityManager will enable dispatching.”

4、mUpdateInputWindowsNeeded

是否需要更新窗口信息到InputDispatcher中的标志。在非强制性更新窗口信息到InputDispatcher中去时,必须先调用InputMonitor.setUpdateInputWindowsNeededLw()设置该标志,然后再调用InputMonitor.updateInputWindowsLw()。如果强制性更新窗口信息到InputDispatcher中去时就不必设置该变量了。

5、mInputDevicesReadyMonitor


6、mInputDevicesReady












InputMonitor笔记