Android源码 native InputManager 与window窗体输入事件分析(完整版)

总体图: 

 

原文链接:Android 源码 输入系统之事件窗口分发_handlereceivecallback-CSDN博客

输入事件的源头是位于 /dev/input/ 下的设备节点,输入事件的终点是由 WindowManagerService 管理的某个窗口处理。

它分为 Java 层和 Native 层两部分。Java 层负责与 WindowManagerService 的通信。而 Native 层则是 InputReader 和 InputDispatcher 两个输入系统关键组件的运行容器。

EventHub 直接访问所有的设备节点。它通过一个名为 getEvents() 的函数将所有输入系统相关的待处理的底层事件返回给使用者。

InputReader,它运行于一个独立的线程中,负责管理输入设备的列表与配置,以及进行输入事件的加工处理。它通过其线程循环不断地通过 getEvents() 函数从 EventHub 中将事件取出并进行处理。交给 InputDispatcher 进行派发。

InputDispatcher 中保管了来自 WindowManagerService 的所有窗口的信息,其收到来自 InputReader 的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口。

当新建窗口时,WindowManagerService 为新窗口和 InputManagerService 创建了事件传递所用的通道。WindowManagerService 还将所有窗口的信息,包括窗口的可点击区域,焦点窗口等信息,实时地更新到 InputManagerService 的 InputDispatcher 中,使得 InputDispatcher 可以正确地将事件派发到指定的窗口。

ViewRootImpl 将窗口所接收到的输入事件沿着控件树将事件派发给感兴趣的控件。

简单来说,内核将原始事件写入到设备节点中,InputReader 不断地通过 EventHub 将原始事件取出来并翻译加工成 Android 输入事件,然后交给 InputDispatcher。InputDispatcher 根据 WindowManagerService 提供的窗口信息将事件交给合适的窗口。窗口的 ViewRootImpl 对象再沿着控件树将事件派发给感兴趣的控件。控件对其收到的事件作出响应,更新自己的画面、执行特定的动作。
 

InputManagerService 初始化

Android 源码 InputManagerService 初始化_/spritecontroller-CSDN博客

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
    ......
    public InputManagerService(Context context) {
        this.mContext = context;
        // 1.创建 InputManagerHandler Handler 类型对象,注意 Looper 是从 DisplayThread 获取的。
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
        // 是否将 dev/input/event 或 uevent 子系统用于音频插孔。
        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                + mUseDevInputEventForAudioJack);
        // 2.native 初始化,返回指向本地输入管理器服务对象的指针。
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());

        LocalServices.addService(InputManagerInternal.class, new LocalService());
    }   
    ......
}
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

NativeInputManager 构造函数

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    // 将 contextObj 和 serviceObj 提升为 jni 全局变量
    mContextObj = env->NewGlobalRef(contextObj);
    mServiceObj = env->NewGlobalRef(serviceObj);

    {
        AutoMutex _l(mLock);
        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
    }
    mInteractive = true;

    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}



NativeInputManager 类继承了 RefBase、InputReaderPolicyInterface、InputDispatcherPolicyInterface 和 PointerControllerPolicyInterface。
可实现引用计数,以及相关策略。Locked 是其私有结构体。


class NativeInputManager : public virtual RefBase,
    public virtual InputReaderPolicyInterface,
    public virtual InputDispatcherPolicyInterface,
    public virtual PointerControllerPolicyInterface {
    ......
private:
    ......
    struct Locked {
        // 显示尺寸信息
        DisplayViewport internalViewport;
        DisplayViewport externalViewport;

        // 系统 UI 可见性
        int32_t systemUiVisibility;

        // 指针速度。
        int32_t pointerSpeed;

        // 如果启用指针手势,则为真。
        bool pointerGesturesEnabled;

        // 显示触摸功能启用/禁用。
        bool showTouches;

        // SpriteController 单例
        sp<SpriteController> spriteController;

        // PointerController 单例
        wp<PointerController> pointerController;
    } mLocked;
    ......
};

EventHub 构造函数

frameworks/native/services/inputflinger/EventHub.cpp

EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(0), mClosingDevices(0),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
    // 创建一个 epoll 对象的描述符
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);

    // 创建一个 inotify 对象
    mINotifyFd = inotify_init();
    // 通过 inotify_add_watch 将一个或多个监听添加到 inotify 对象中
    int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
    LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",
            DEVICE_PATH, errno);
    // 填充 epoll_event
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;// 监听可读事件
    eventItem.data.u32 = EPOLL_ID_INOTIFY;// 自定义 ID,当事件返回时可知是以上定义的 inotify 相关
    // 将 inotify 事件监听添加到 epoll 对象中去
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);

    int wakeFds[2];
    // 创建管道
    result = pipe(wakeFds);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
    // 读端文件描述符
    mWakeReadPipeFd = wakeFds[0];
    // 写端文件描述符
    mWakeWritePipeFd = wakeFds[1];
    // 将管道读端设为非阻塞模式
    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
            errno);
    // 将管道写端设为非阻塞模式
    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
            errno);

    eventItem.data.u32 = EPOLL_ID_WAKE;// 自定义 ID,当事件返回时可知是以上定义的 Pipe 相关
    // 将管道事件监听添加到 epoll 对象中去
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
            errno);

    int major, minor;
    // 获取内核版本号
    getLinuxRelease(&major, &minor);
    // EPOLLWAKEUP 是内核 3.5 中引入的
    mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);
}

InputManager 对象创建

InputManager 是系统事件处理的核心,它使用了两个线程。

1.InputReaderThread(称为“ InputReader”)读取并预处理原始输入事件,应用策略,并将消息发布到由 DispatcherThread 管理的队列中。

2.InputDispatcherThread(称为“ InputDispatcher”)线程在队列上等待新事件,并异步将其分配给应用程序。
所有通信都是从 InputReaderThread 到 InputDispatcherThread 的一种方式,绝不会反转。但是,这两个类都可以与 InputDispatchPolicy 交互。InputDispatchPolicy 负责执行与系统的所有外部交互。

InputManager 构造器中创建了 InputDispatcher 和 InputReader 对象,initialize 方法启动了两个线程 InputReaderThread 和 InputDispatcherThread。

frameworks/native/services/inputflinger/InputManager.h

namespace android {
class InputManagerInterface : public virtual RefBase {
protected:
    InputManagerInterface() { }
    virtual ~InputManagerInterface() { }

public:
    /* 启动 InputManager 线程 */
    virtual status_t start() = 0;
    /* 停止 InputManager 线程并等待它们退出 */
    virtual status_t stop() = 0;
    /* 获取 InputReader */
    virtual sp<InputReaderInterface> getReader() = 0;
    /* 获取 InputDispatcher */
    virtual sp<InputDispatcherInterface> getDispatcher() = 0;
};

class InputManager : public InputManagerInterface {
protected:
    virtual ~InputManager();

public:
    InputManager(
            const sp<EventHubInterface>& eventHub,
            const sp<InputReaderPolicyInterface>& readerPolicy,
            const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
    // (测试目的)
    InputManager(
            const sp<InputReaderInterface>& reader,
            const sp<InputDispatcherInterface>& dispatcher);

    virtual status_t start();
    virtual status_t stop();

    virtual sp<InputReaderInterface> getReader();
    virtual sp<InputDispatcherInterface> getDispatcher();

private:
    sp<InputReaderInterface> mReader;
    sp<InputReaderThread> mReaderThread;

    sp<InputDispatcherInterface> mDispatcher;
    sp<InputDispatcherThread> mDispatcherThread;

    void initialize();
};

} // namespace android

frameworks/native/services/inputflinger/InputManager.cpp

namespace android {

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    // 1.创建 InputDispatcher 对象
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    // 2.创建 InputReader 对象
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

......
void InputManager::initialize() {
    // 3.创建 InputReaderThread 对象
    mReaderThread = new InputReaderThread(mReader);
    // 4.创建 InputDispatcherThread 对象
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
......

} // namespace android
创建 InputDispatcher 对象
namespace android {
......
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
    mPolicy(policy),
    mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
    mNextUnblockedEvent(NULL),
    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
    mLooper = new Looper(false);

    mKeyRepeatState.lastKeyEntry = NULL;

    policy->getDispatcherConfiguration(&mConfig);
}
......
}
创建 InputReader 对象
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) {
    mQueuedListener = new QueuedInputListener(listener);//交付给 InputDispatcher。

    { // acquire lock
        AutoMutex _l(mLock);

        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}

InputManagerService 启动

frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer {
    ......
    public static void main(String[] args) {
        new SystemServer().run();
    }
    ......
    private void run() {
        ......
        try {
            ......
            startOtherServices();
        } catch (Throwable ex) {
            ......
        }
        ......
    }
    ......
    private void startOtherServices() {
        ......
        WindowManagerService wm = null;
        ......
        InputManagerService inputManager = null;
        ......
        try {
            ......
            // 启动 InputManagerService
            inputManager.start();
            ......
        } catch (RuntimeException e) {
            ......
        }
    }
    ......
}


nativeStart 

public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
    ......
    public void start() {
        Slog.i(TAG, "Starting input manager");
        // mPtr 是指向 native input manager 服务对象的指针
        nativeStart(mPtr);

        // 添加到看门狗监视器
        Watchdog.getInstance().addMonitor(this);

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

    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}
frameworks/native/services/inputflinger/InputManager.cpp

status_t InputManager::start() {
    // 1.启动 DispatcherThread
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }
    // 2.启动 ReaderThread
    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    if (result) {
        ALOGE("Could not start InputReader thread due to error %d.", result);
        // 请求退出 DispatcherThread
        mDispatcherThread->requestExit();
        return result;
    }

    return OK;
}

InputReader

threadLoop() 函数实际上调用了 InputReader loopOnce() 方法。

Android 源码 输入系统之 InputReader_inputreader的作用-CSDN博客

bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

loopOnce 从方法名可知是轮训一次的意思。

从 EventHub 中读取未处理的事件列表。这些事件分为两类,一类是从设备节点中读取的原始输入事件;另一类则是设备事件。

通过 processEventsLocked() 对事件进行处理。对于设备事件,此函数对根据设备的可用性加载或移除设备对应的配置信息。对于原始输入事件,则在进行转译、封装与加工后将结果暂存到 mQueuedListener 中。

所有事件处理完毕后,调用 mQueuedListener.flush() 将所有暂存的输入事件一次性地交付给 InputDispatcher。
 

void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    Vector<InputDeviceInfo> inputDevices;
    { // acquire lock
        AutoMutex _l(mLock);

        oldGeneration = mGeneration;
        timeoutMillis = -1;

        uint32_t changes = mConfigurationChangesToRefresh;
        if (changes) {
            mConfigurationChangesToRefresh = 0;
            timeoutMillis = 0;
            // 刷新配置
            refreshConfigurationLocked(changes);
        } else if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            // 计算当前距离下次超时的时间差
            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
        }
    } // release lock
    // 1.获取原始输入事件。当 EventHub 中无事件可以读取时,此函数调用将会阻塞直到事件到来或者超时。
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

    { // acquire lock
        AutoMutex _l(mLock);
        mReaderIsAliveCondition.broadcast();

        if (count) {
            // 2.处理事件
            processEventsLocked(mEventBuffer, count);
        }

        if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            if (now >= mNextTimeout) {
#if DEBUG_RAW_EVENTS
                ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
                mNextTimeout = LLONG_MAX;
                timeoutExpiredLocked(now);
            }
        }

        if (oldGeneration != mGeneration) {
            inputDevicesChanged = true;
            // 获取输入设备
            getInputDevicesLocked(inputDevices);
        }
    } // release lock

    // 发送一条消息,描述已更改的输入设备。
    if (inputDevicesChanged) {
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }

    // 3.将排队的事件刷新给 listener。
    // 这必须在锁之外发生,因为 listener 可能会回调到 InputReader 的方法(如 getScanCodeState),
    // 或者被另一个线程阻塞,类似地等待获取 InputReader 锁,从而导致死锁。
    // 这种情况实际上是很合理的,因为 listener 实际上是 InputDispatcher,
    // 它调用窗口管理器,而窗口管理器偶尔调用 InputReader。
    mQueuedListener->flush();
}

EventHub::getEvents() 函数 

getEvents() 函数使用 Epoll 机制的核心是 mPendingEventItems 数组,它是一个事件池。

InputReader::processEventsLocked 事件处理函数 

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
            while (batchSize < count) {
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                        || rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1;
            }
#if DEBUG_RAW_EVENTS
            ALOGD("BatchSize: %d Count: %d", batchSize, count);
#endif
            // 1.处理设备原始输入事件
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
            switch (rawEvent->type) {
            case EventHubInterface::DEVICE_ADDED:
                // 2.处理设备添加事件
                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::DEVICE_REMOVED:
                // 3.处理设备移除事件
                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::FINISHED_DEVICE_SCAN:
                // 4.处理扫描结束事件,所有添加/删除设备从最近的扫描已报告
                handleConfigurationChangedLocked(rawEvent->when);
                break;
            default:
                ALOG_ASSERT(false); // can't happen
                break;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}

KeyboardInputMapper::processKey

void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
        int32_t usageCode) {
    int32_t keyCode;
    int32_t keyMetaState;
    uint32_t policyFlags;
    // 1.mapKey 获得 keyCode 等
    if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState,
                              &keyCode, &keyMetaState, &policyFlags)) {
        keyCode = AKEYCODE_UNKNOWN;
        keyMetaState = mMetaState;
        policyFlags = 0;
    }

    if (down) {
        ......
        // 添加按键按下
        ssize_t keyDownIndex = findKeyDown(scanCode);
        if (keyDownIndex >= 0) {
            ......
        } else {
            // 按键按下,第一次按下进入此分支,向 mKeyDowns 中添加一个 KeyDown 对象,
            // 此对象包括了按键扫描码和键码
            ......
            mKeyDowns.push();
            KeyDown& keyDown = mKeyDowns.editTop();
            keyDown.keyCode = keyCode;
            keyDown.scanCode = scanCode;
        }

        mDownTime = when;
    } else {
        // 按键抬起,从按键按下 mKeyDowns Vector 中删除对应项
        ssize_t keyDownIndex = findKeyDown(scanCode);
        if (keyDownIndex >= 0) {
            // key up, be sure to use same keycode as before in case of rotation
            keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
            mKeyDowns.removeAt(size_t(keyDownIndex));
        } else {
            // key was not actually down
            ALOGI("Dropping key up from device %s because the key was not down.  "
                    "keyCode=%d, scanCode=%d",
                    getDeviceName().string(), keyCode, scanCode);
            return;
        }
    }

    ......

    nsecs_t downTime = mDownTime;

    // 按下外部键盘将设备唤醒。
    // 我们不对内置键盘执行此操作,以防止它们从口袋里醒来。
    // 对于内部键盘,键布局文件应分别为每个唤醒键指定策略标志。
    if (down && getDevice()->isExternal()) {
        policyFlags |= POLICY_FLAG_WAKE;
    }

    ......

    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
    // 2.将 NotifyKeyArgs 添加到 QueuedInputListener 内部 mArgsQueue 中
    getListener()->notifyKey(&args);
}

NotifyKeyArgs::NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
        uint32_t policyFlags,
        int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
        int32_t metaState, nsecs_t downTime) :
        eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags),
        action(action), flags(flags), keyCode(keyCode), scanCode(scanCode),
        metaState(metaState), downTime(downTime) {
}

void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
    mArgsQueue.push(new NotifyKeyArgs(*args));
}

mQueuedListener  flush() 方法

内部其实调用了 InputListenerInterface 对象的 notifyKey 方法,传入的实参是 NotifyKeyArgs 对象自身。

void QueuedInputListener::flush() {
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        args->notify(mInnerListener);
        delete args;
    }
    mArgsQueue.clear();
}
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
    listener->notifyKey(this);
}

QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
        mInnerListener(innerListener) {
}
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) {
    mQueuedListener = new QueuedInputListener(listener);//构造 QueuedInputListener 对象的代码,传入的实参是 InputDispatcher 对象 mDispatcher。这说明 InputDispatcher 继承了 InputListenerInterface 类。
    ......
}

InputDispatcher 类并没有直接继承 InputListenerInterface 类,而是继承了 InputDispatcherInterface 类。 InputDispatcherInterface 类一定继承了 InputListenerInterface 类。

其目的实际上是把事件队列加入 mInboundQueue,但是在插入 mInboundQueue 队列尾部之前,调用了interceptKeyBeforeQueueing,该函数通过 jni 调用到 PhoneWindowManager 的 interceptKeyBeforeQueueing,比如 power 键就是在 interceptKeyBeforeQueueing 中处理的。插入 mInboundQueue 队列尾部成功后,就会调用 Looper wake 函数去唤醒 InputDispatcherThread。
 

InputDispatcher

InputDispatcher::notifyKey

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    ......
    // 验证按键事件是否有效
    if (!validateKeyEvent(args->action)) {
        return;
    }
    ......
    // 创建 KeyEvent 对象
    KeyEvent event;
    event.initialize(args->deviceId, args->source, args->action,
            flags, keyCode, args->scanCode, metaState, 0,
            args->downTime, args->eventTime);
    // 在排队之前,先拦截触摸,轨迹球或其他运动事件。
    // 策略可以将此方法用作执行电源管理功能和早期事件预处理(例如更新策略标志)的机会。
    // 如果应将事件分派给应用程序,则此方法应设置POLICY_FLAG_PASS_TO_USER策略标志。
    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);

    bool needWake;
    { // acquire lock
        mLock.lock();

        ......

        int32_t repeatCount = 0;
        // 创建 KeyEntry 对象
        KeyEntry* newEntry = new KeyEntry(args->eventTime,
                args->deviceId, args->source, policyFlags,
                args->action, flags, keyCode, args->scanCode,
                metaState, repeatCount, args->downTime);
        // 将 KeyEntry 对象添加到 mInboundQueue 队列尾部
        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    } // release lock
    // 是否唤醒
    if (needWake) {
        mLooper->wake();
    }
}

InputDispatcher::dispatchOnce

bool InputDispatcherThread::threadLoop() {
    mDispatcher->dispatchOnce();
    return true;
}
void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        AutoMutex _l(mLock);
        mDispatcherIsAliveCondition.broadcast();

        // 如果没有挂起的命令,则运行分派循环。分派循环可能会对以后运行的命令进行排队。
        if (!haveCommandsLocked()) {
            dispatchOnceInnerLocked(&nextWakeupTime);
        }

        // 运行所有挂起的命令(如果有的话)。如果运行了任何命令,则强制立即唤醒下一个轮询。
        if (runCommandsLockedInterruptible()) {
            nextWakeupTime = LONG_LONG_MIN;
        }
    } // release lock

    // 等待回调、超时或唤醒。
    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    mLooper->pollOnce(timeoutMillis);
}

InputDispatcher::dispatchOnceInnerLocked 

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

    // 当设备处于非交互状态时,当正常分派被挂起时,重置键重复计时器。
    if (!mDispatchEnabled) {
        resetKeyRepeatLocked();
    }

    // 如果分派被冻结,请勿处理超时或尝试传递任何新事件。
    if (mDispatchFrozen) {
#if DEBUG_FOCUS
        ALOGD("Dispatch frozen.  Waiting some more.");
#endif
        return;
    }

    // 优化应用程序切换的延迟。
    // 实际上,当应用程序切换键(HOME/ENDCALL)被按下时,我们会启动一个短暂的超时。
    // 当它过期时,我们抢占分派并删除所有其他挂起事件。
    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
    if (mAppSwitchDueTime < *nextWakeupTime) {
        *nextWakeupTime = mAppSwitchDueTime;
    }

    // 准备启动一个新事件。
    // 如果我们还没有一个挂起的事件,去抓一个。
    if (! mPendingEvent) {
        if (mInboundQueue.isEmpty()) {
            if (isAppSwitchDue) {
                // mInboundQueue 为空,因此我们等待的应用程序切换键永远不会到达。别再等了。
                resetPendingAppSwitchLocked(false);
                isAppSwitchDue = false;
            }

            // 如果合适,合成一个重复的按键。
            if (mKeyRepeatState.lastKeyEntry) {
                if (currentTime >= mKeyRepeatState.nextRepeatTime) {
                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
                } else {
                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
                    }
                }
            }

            // 如果没有挂起事件,则什么也不做。
            if (!mPendingEvent) {
                return;
            }
        } else {
            // mInboundQueue 至少有一个条目,从队列头部取出一个事件。
            mPendingEvent = mInboundQueue.dequeueAtHead();
            traceInboundQueueLengthLocked();
        }

        // 直接发送到用户的事件,不用考虑当前 Activity
        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            pokeUserActivityLocked(mPendingEvent);
        }

        // 重置 ANR 超时。
        resetANRTimeoutsLocked();
    }

    // 现在我们要分派一个事件。
    // 所有事件最终都会以这种方式离开队列和处理,即使我们打算删除它们。
    ALOG_ASSERT(mPendingEvent != NULL);
    bool done = false;
    DropReason dropReason = DROP_REASON_NOT_DROPPED;
    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
        dropReason = DROP_REASON_POLICY;
    } else if (!mDispatchEnabled) {
        dropReason = DROP_REASON_DISABLED;
    }

    if (mNextUnblockedEvent == mPendingEvent) {
        mNextUnblockedEvent = NULL;
    }

    switch (mPendingEvent->type) {
    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
        ConfigurationChangedEntry* typedEntry =
                static_cast<ConfigurationChangedEntry*>(mPendingEvent);
        // 配置更改事件分发
        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
        dropReason = DROP_REASON_NOT_DROPPED; // 配置更改永远不会被删除
        break;
    }

    case EventEntry::TYPE_DEVICE_RESET: {
        DeviceResetEntry* typedEntry =
                static_cast<DeviceResetEntry*>(mPendingEvent);
        // 设备重置事件分发
        done = dispatchDeviceResetLocked(currentTime, typedEntry);
        dropReason = DROP_REASON_NOT_DROPPED; // 设备重置不会被丢弃
        break;
    }

    case EventEntry::TYPE_KEY: {
        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
        if (isAppSwitchDue) {
            if (isAppSwitchKeyEventLocked(typedEntry)) {
                resetPendingAppSwitchLocked(true);
                isAppSwitchDue = false;
            } else if (dropReason == DROP_REASON_NOT_DROPPED) {
                dropReason = DROP_REASON_APP_SWITCH;
            }
        }
        if (dropReason == DROP_REASON_NOT_DROPPED
                && isStaleEventLocked(currentTime, typedEntry)) {
            dropReason = DROP_REASON_STALE;
        }
        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
            dropReason = DROP_REASON_BLOCKED;
        }
        // 按键事件分发
        done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
        break;
    }

    case EventEntry::TYPE_MOTION: {
        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
            dropReason = DROP_REASON_APP_SWITCH;
        }
        if (dropReason == DROP_REASON_NOT_DROPPED
                && isStaleEventLocked(currentTime, typedEntry)) {
            dropReason = DROP_REASON_STALE;
        }
        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
            dropReason = DROP_REASON_BLOCKED;
        }
        // 触摸事件分发
        done = dispatchMotionLocked(currentTime, typedEntry,
                &dropReason, nextWakeupTime);
        break;
    }

    default:
        ALOG_ASSERT(false);
        break;
    }

    if (done) {
        if (dropReason != DROP_REASON_NOT_DROPPED) {
            dropInboundEventLocked(mPendingEvent, dropReason);
        }
        mLastDropReason = dropReason;

        releasePendingEventLocked();
        *nextWakeupTime = LONG_LONG_MIN;  // 强制下一次 poll 立即唤醒
    }
}

InputDispatcher::dispatchKeyLocked

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
        DropReason* dropReason, nsecs_t* nextWakeupTime) {
    if (! entry->dispatchInProgress) {
        if (entry->repeatCount == 0
                && entry->action == AKEY_EVENT_ACTION_DOWN
                && (entry->policyFlags & POLICY_FLAG_TRUSTED)
                && (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
            if (mKeyRepeatState.lastKeyEntry
                    && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
                // 我们已经连续看到两次相同的按键按下,
                // 这表明设备驱动程序会自动生成自己的按键重复。
                // 我们在这里记下了重复,但是由于显然我们不需要自己合成按键重复,
                // 因此我们禁用了自己的下一个按键重复计时器。
                entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
                resetKeyRepeatLocked();
                // 不需要自己合成按键重复,将下次重复时间设置为 LONG_LONG_MAX
                mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX;
            } else {
                // 不是一个重复。保存键按下状态,以防我们稍后看到按键重复。
                resetKeyRepeatLocked();
                mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
            }
            mKeyRepeatState.lastKeyEntry = entry;
            entry->refCount += 1;
        } else if (! entry->syntheticRepeat) {
            resetKeyRepeatLocked();
        }

        if (entry->repeatCount == 1) {
            entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
        } else {
            entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
        }

        entry->dispatchInProgress = true;

        logOutboundKeyDetailsLocked("dispatchKey - ", entry);
    }

    // 处理上次策略要求我们稍后再试的情况。
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
        if (currentTime < entry->interceptKeyWakeupTime) {
            if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
                *nextWakeupTime = entry->interceptKeyWakeupTime;
            }
            return false; // 等到下一次醒来
        }
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
        entry->interceptKeyWakeupTime = 0;
    }

    // 给策略一个拦截按键的机会。
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            CommandEntry* commandEntry = postCommandLocked(
                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            if (mFocusedWindowHandle != NULL) {
                commandEntry->inputWindowHandle = mFocusedWindowHandle;
            }
            commandEntry->keyEntry = entry;
            entry->refCount += 1;
            return false; // 等待命令运行
        } else {
            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
        }
    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
        if (*dropReason == DROP_REASON_NOT_DROPPED) {
            *dropReason = DROP_REASON_POLICY;
        }
    }

    // 如果删除事件,请清理。
    if (*dropReason != DROP_REASON_NOT_DROPPED) {
        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
        return true;
    }

    Vector<InputTarget> inputTargets;
    // 1.确定派发目标
    int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
            entry, inputTargets, nextWakeupTime);
    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
        return false;
    }

    setInjectionResultLocked(entry, injectionResult);
    if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
        return true;
    }

    addMonitoringTargetsLocked(inputTargets);

    // 2.派发按键事件
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

确定当前焦点窗口句柄派发目标 inputChannel

addWindowTargetLocked 将当前焦点窗口句柄(mFocusedWindowHandle)信息赋值给 InputTarget 对象。这个对象 push 到 inputTargets Vector 中,其中最重要的信息莫过于 inputChannel.

int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
        const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
    int32_t injectionResult;
    String8 reason;

    // 如果当前没有焦点窗口,也没有焦点的应用程序,则删除事件。
    if (mFocusedWindowHandle == NULL) {
        if (mFocusedApplicationHandle != NULL) {
            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;
        }

        ALOGI("Dropping event because there is no focused window or focused application.");
        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;
    }

    // 成功!输出目标。
    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);
#if DEBUG_FOCUS
    ALOGD("findFocusedWindow finished: injectionResult=%d, "
            "timeSpentWaitingForApplication=%0.1fms",
            injectionResult, timeSpentWaitingForApplication / 1000000.0);
#endif
    return injectionResult;
}


void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
        int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {
    inputTargets.push();

    const InputWindowInfo* windowInfo = windowHandle->getInfo();
    InputTarget& target = inputTargets.editTop();
    target.inputChannel = windowInfo->inputChannel;
    target.flags = targetFlags;
    target.xOffset = - windowInfo->frameLeft;
    target.yOffset = - windowInfo->frameTop;
    target.scaleFactor = windowInfo->scaleFactor;
    target.pointerIds = pointerIds;
}

InputDispatcher::dispatchEventLocked

void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
        EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
    ......

    for (size_t i = 0; i < inputTargets.size(); i++) {
        const InputTarget& inputTarget = inputTargets.itemAt(i);

        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
        if (connectionIndex >= 0) {
            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
        } else {
            ......
        }
    }
}
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    ......
    // 如果连接状态不正常,跳过此事件。
    if (connection->status != Connection::STATUS_NORMAL) {
#if DEBUG_DISPATCH_CYCLE
        ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
                connection->getInputChannelName(), connection->getStatusLabel());
#endif
        return;
    }

    // 如果需要,拆分动作事件;
    
    if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
        ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION);

        MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
        if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
            MotionEntry* splitMotionEntry = splitMotionEvent(
                    originalMotionEntry, inputTarget->pointerIds);
            if (!splitMotionEntry) {
                return; // 拆分事件已删除
            }
#if DEBUG_FOCUS
            ALOGD("channel '%s' ~ Split motion event.",
                    connection->getInputChannelName());
            logOutboundMotionDetailsLocked("  ", splitMotionEntry);
#endif
            enqueueDispatchEntriesLocked(currentTime, connection,
                    splitMotionEntry, inputTarget);
            splitMotionEntry->release();
            return;
        }
    }

    // 不拆分事件。使事件的派发条目按原样排队。
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}

把事件入 outboundQueue 队列,这里的队列不同于 inboundQueue,outboundQueue 是窗口相关的,窗口跟 InputDispatcherThread 间建立起一个连接(connection),该 outboundQueue 就是 connection 的成员。
 

void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
    bool wasEmpty = connection->outboundQueue.isEmpty();

    // 使请求的模式的派发条目入队。
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
            InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
            InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
            InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
            InputTarget::FLAG_DISPATCH_AS_IS);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
            InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);

    // 如果 outboundQueue 不为空,则开始派发。
    if (wasEmpty && !connection->outboundQueue.isEmpty()) {
        startDispatchCycleLocked(currentTime, connection);
    }
}

InputDispatcher::enqueueDispatchEntryLocked 

void InputDispatcher::enqueueDispatchEntryLocked(
        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
        int32_t dispatchMode) {
    int32_t inputTargetFlags = inputTarget->flags;
    if (!(inputTargetFlags & dispatchMode)) {
        return;
    }
    inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;

    // 这是一个新的事件。
    // 将新的派发条目排队到该连接的 outboundQueue 中。
    DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
            inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
            inputTarget->scaleFactor);

    // 应用目标标志并更新连接的输入状态。
    switch (eventEntry->type) {
    case EventEntry::TYPE_KEY: {
        KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
        dispatchEntry->resolvedAction = keyEntry->action;
        dispatchEntry->resolvedFlags = keyEntry->flags;
        // 跳过不一致的按键事件
        if (!connection->inputState.trackKey(keyEntry,
                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
#if DEBUG_DISPATCH_CYCLE
            ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
                    connection->getInputChannelName());
#endif
            delete dispatchEntry;
            return; // skip the inconsistent event
        }
        break;
    }

    case EventEntry::TYPE_MOTION: {
        MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
        if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
        } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
        } else {
            dispatchEntry->resolvedAction = motionEntry->action;
        }
        if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
                && !connection->inputState.isHovering(
                        motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) {
#if DEBUG_DISPATCH_CYCLE
        ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
                connection->getInputChannelName());
#endif
            dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
        }

        dispatchEntry->resolvedFlags = motionEntry->flags;
        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
            dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
        }
        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
            dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
        }
        // 跳过不一致的动作事件
        if (!connection->inputState.trackMotion(motionEntry,
                dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
#if DEBUG_DISPATCH_CYCLE
            ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
                    connection->getInputChannelName());
#endif
            delete dispatchEntry;
            return; // skip the inconsistent event
        }
        break;
    }
    }

    // 请记住,我们正在等待此派发完成。
    if (dispatchEntry->hasForegroundTarget()) {
        incrementPendingForegroundDispatchesLocked(eventEntry);
    }

    // 使派发条目入队。
    connection->outboundQueue.enqueueAtTail(dispatchEntry);
    traceOutboundQueueLengthLocked(connection);
}

InputDispatcher::startDispatchCycleLocked

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection) {
#if DEBUG_DISPATCH_CYCLE
    ALOGD("channel '%s' ~ startDispatchCycle",
            connection->getInputChannelName());
#endif

    while (connection->status == Connection::STATUS_NORMAL
            && !connection->outboundQueue.isEmpty()) {
        DispatchEntry* dispatchEntry = connection->outboundQueue.head;
        dispatchEntry->deliveryTime = currentTime;

        // 发布事件。
        status_t status;
        EventEntry* eventEntry = dispatchEntry->eventEntry;
        switch (eventEntry->type) {
        case EventEntry::TYPE_KEY: {
            KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);

            // 发布按键事件
            status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
                    keyEntry->deviceId, keyEntry->source,
                    dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
                    keyEntry->keyCode, keyEntry->scanCode,
                    keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
                    keyEntry->eventTime);
            break;
        }

        case EventEntry::TYPE_MOTION: {
            MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);

            PointerCoords scaledCoords[MAX_POINTERS];
            const PointerCoords* usingCoords = motionEntry->pointerCoords;

            // 根据输入源设置X和Y偏移。
            float xOffset, yOffset, scaleFactor;
            if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                    && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
                scaleFactor = dispatchEntry->scaleFactor;
                xOffset = dispatchEntry->xOffset * scaleFactor;
                yOffset = dispatchEntry->yOffset * scaleFactor;
                if (scaleFactor != 1.0f) {
                    for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
                        scaledCoords[i] = motionEntry->pointerCoords[i];
                        scaledCoords[i].scale(scaleFactor);
                    }
                    usingCoords = scaledCoords;
                }
            } else {
                xOffset = 0.0f;
                yOffset = 0.0f;
                scaleFactor = 1.0f;

                // 我们不希望派发目标知道。
                if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
                    for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
                        scaledCoords[i].clear();
                    }
                    usingCoords = scaledCoords;
                }
            }

            // 发布动作事件。
            status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
                    motionEntry->deviceId, motionEntry->source,
                    dispatchEntry->resolvedAction, motionEntry->actionButton,
                    dispatchEntry->resolvedFlags, motionEntry->edgeFlags,
                    motionEntry->metaState, motionEntry->buttonState,
                    xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision,
                    motionEntry->downTime, motionEntry->eventTime,
                    motionEntry->pointerCount, motionEntry->pointerProperties,
                    usingCoords);
            break;
        }

        default:
            ALOG_ASSERT(false);
            return;
        }

        // 检查结果。
        if (status) {
            if (status == WOULD_BLOCK) {
                if (connection->waitQueue.isEmpty()) {
                    ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
                            "This is unexpected because the wait queue is empty, so the pipe "
                            "should be empty and we shouldn't have any problems writing an "
                            "event to it, status=%d", connection->getInputChannelName(), status);
                    abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
                } else {
                    // 管道已满,我们正在等待应用程序处理一些事件,然后再向其发送更多事件。
#if DEBUG_DISPATCH_CYCLE
                    ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
                            "waiting for the application to catch up",
                            connection->getInputChannelName());
#endif
                    connection->inputPublisherBlocked = true;
                }
            } else {
                ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
                        "status=%d", connection->getInputChannelName(), status);
                abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
            }
            return;
        }

        // 将事件重新加入等待队列(waitQueue)。
        connection->outboundQueue.dequeue(dispatchEntry);
        traceOutboundQueueLengthLocked(connection);
        connection->waitQueue.enqueueAtTail(dispatchEntry);
        traceWaitQueueLengthLocked(connection);
    }
}

InputPublisher::publishKeyEvent

先构建 InputMessage 消息对象,然后调用 InputChannel 的 sendMessage 将消息发送出去。实际是调用 socket 的 send 接口来发送消息的。

status_t InputPublisher::publishKeyEvent(
        uint32_t seq,
        int32_t deviceId,
        int32_t source,
        int32_t action,
        int32_t flags,
        int32_t keyCode,
        int32_t scanCode,
        int32_t metaState,
        int32_t repeatCount,
        nsecs_t downTime,
        nsecs_t eventTime) {
    ......

    if (!seq) {
        ALOGE("Attempted to publish a key event with sequence number 0.");
        return BAD_VALUE;
    }

    InputMessage msg;
    msg.header.type = InputMessage::TYPE_KEY;
    msg.body.key.seq = seq;
    msg.body.key.deviceId = deviceId;
    msg.body.key.source = source;
    msg.body.key.action = action;
    msg.body.key.flags = flags;
    msg.body.key.keyCode = keyCode;
    msg.body.key.scanCode = scanCode;
    msg.body.key.metaState = metaState;
    msg.body.key.repeatCount = repeatCount;
    msg.body.key.downTime = downTime;
    msg.body.key.eventTime = eventTime;
    return mChannel->sendMessage(&msg);
}
status_t InputChannel::sendMessage(const InputMessage* msg) {
    size_t msgLength = msg->size();
    ssize_t nWrite;
    do {
        nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
    } while (nWrite == -1 && errno == EINTR);

    if (nWrite < 0) {
        int error = errno;
        ......
        if (error == EAGAIN || error == EWOULDBLOCK) {
            return WOULD_BLOCK;
        }
        if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
            return DEAD_OBJECT;
        }
        return -error;
    }

    if (size_t(nWrite) != msgLength) {
        ......
        return DEAD_OBJECT;
    }
    ......
    return OK;
}

具体窗口如何接收事件我们还没有进行分析,另外窗口处理了事件后,如何通知 InputDispatcher 删除 waitQueue 中的相应事件也需要进一步了解

输入系统之窗口关联

Android 源码 输入系统之窗口关联-CSDN博客

mFocusedWindowHandle 是 InputDispatcher 的成员变量,它是确定发送事件消息的关键。我们以它为突破口寻找“出路”。mFocusedWindowHandle 在 setInputWindows 方法中进行了赋值。


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;
        bool foundHoveredWindow = false;
        for (size_t i = 0; i < mWindowHandles.size(); i++) {
            const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
            if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) {
                mWindowHandles.removeAt(i--);
                continue;
            }
            if (windowHandle->getInfo()->hasFocus) {
                // 找到焦点窗口句柄
                newFocusedWindowHandle = windowHandle;
            }
            ......
        }

        ......

        if (mFocusedWindowHandle != newFocusedWindowHandle) {
            if (mFocusedWindowHandle != NULL) {
                sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
                if (focusedInputChannel != NULL) {
                    CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
                            "focus left window");
                    synthesizeCancelationEventsForInputChannelLocked(
                            focusedInputChannel, options);
                }
            }
            // mFocusedWindowHandle 赋值焦点窗口句柄
            mFocusedWindowHandle = newFocusedWindowHandle;
        }

        ......
    } // release lock

    // 唤醒 Looper 循环,因为它可能需要作出新的输入派发选择。
    mLooper->wake();
}

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);
}



void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
    Vector<sp<InputWindowHandle> > windowHandles;

    if (windowHandleObjArray) {
        jsize length = env->GetArrayLength(windowHandleObjArray);
        for (jsize i = 0; i < length; i++) {
            jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i);
            if (! windowHandleObj) {
                break; // found null element indicating end of used portion of the array
            }
            // 将数组中的 java 对象转化为 native 对象
            sp<InputWindowHandle> windowHandle =
                    android_server_InputWindowHandle_getHandle(env, windowHandleObj);
            if (windowHandle != NULL) {
                //push 到容器中
                windowHandles.push(windowHandle);
            }
            env->DeleteLocalRef(windowHandleObj);
        }
    }
    // 调用 InputDispatcher setInputWindows 方法
    mInputManager->getDispatcher()->setInputWindows(windowHandles);
    ......
}

但可以确信的一点是,窗口和 InputDispatcher 关联,必须要调用 InputManagerService 类中的 setInputWindows 方法。

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
    ......
    private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
    ......
    public void setInputWindows(InputWindowHandle[] windowHandles) {
        nativeSetInputWindows(mPtr, windowHandles);
    }
    ......
}

Activity setContentView 说起

getWindow() 返回的是一个 PhoneWindow 对象,现在转入 PhoneWindow 类的 setContentView 方法。在 Activity 启动流程分析中,我们知道启动一个 Activity 当调用了 ActivityThread 中 handleLaunchActivity 方法后,马上就会调用 handleResumeActivity 方法,奥秘就在这里!

  1. 获取 Window 和 DecorView 对象;
  2. 设置 DecorView 为不可见;
  3. 获取 WindowManager 对象;
  4. 将 DecorView 添加到 ViewManager。
public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback {
    ......
    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }
    ......
}


public class PhoneWindow extends Window implements MenuBuilder.Callback {
    ......
    @Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            ......
        }

        ......
    }

    ......
}


public class PhoneWindow extends Window implements MenuBuilder.Callback {
    ......
    private void installDecor() {
        if (mDecor == null) {
            mDecor = generateDecor();
            ......
        }
        ......
    }
    ......
}


public final class ActivityThread {
    ......
    final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume) {
        ......
        // TODO Push resumeArgs into the activity for consideration
        ActivityClientRecord r = performResumeActivity(token, clearHide);

        if (r != null) {
            final Activity a = r.activity;
            ......
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                // 设置 DecorView 为不可见
                decor.setVisibility(View.INVISIBLE);
                // 获取 WindowManager 对象
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    // 将 DecorView 添加到 ViewManager
                    wm.addView(decor, l);
                }

            } else if (!willBeVisible) {
                ......
            }

            ......

            // 告诉活动管理器我们已经恢复。
            if (reallyResume) {
                try {
                    ActivityManagerNative.getDefault().activityResumed(token);
                } catch (RemoteException ex) {
                }
            }

        } else {
            ......
        }
    }
    ......
}

WindowManagerGlobal 单例的 addView 方法

上一步 wm 局部变量实际指向 WindowManagerImpl 对象,所以实际调用了 WindowManagerImpl 类的 addView 方法。此处有调用了 WindowManagerGlobal 单例的 addView 方法。

public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    ......
    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mDisplay, mParentWindow);
    }
    ......
}
  1. 创建 ViewRootImpl 对象;
  2. 调用 ViewRootImpl 类 setView 方法。
public final class WindowManagerGlobal {
    ......
    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        ......
        ViewRootImpl root;
        View panelParentView = null;

        synchronized (mLock) {
            ......
            root = new ViewRootImpl(view.getContext(), display);
            ......
        }

        try {
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
            ......
        }
    }
    ......
}
  1. 创建 InputChannel 对象;
  2. 远程调用 Session addToDisplay 方法;
  3. 创建接收输入事件者 WindowInputEventReceiver。

ViewRootImpl.setView

重点关注 Session 类 addToDisplay 方法。

Session 类表示活动的客户端会话。通常,每个与窗口管理器交互的进程都有一个 Session 对象。

addToDisplay 方法实际工作由 WindowManagerService 类 addWindow 方法完成。

 

frameworks/base/core/java/android/view/ViewRootImpl.java

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;
                ......
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    mInputChannel = new InputChannel();
                }
                try {
                    ......
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
                } catch (RemoteException e) {
                    ......
                } finally {
                    ......
                }
                ......
                if (mInputChannel != null) {
                    if (mInputQueueCallback != null) {
                        mInputQueue = new InputQueue();
                        mInputQueueCallback.onInputQueueCreated(mInputQueue);
                    }
                    // 接收输入事件
                    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
                }
                ......
            }
        }
    }
    ......
}

Session 类表示活动的客户端会话。通常,每个与窗口管理器交互的进程都有一个 Session 对象。

addToDisplay 方法实际工作由 WindowManagerService 类 addWindow 方法完成。

frameworks/base/services/core/java/com/android/server/wm/Session.java

final class Session extends IWindowSession.Stub
        implements IBinder.DeathRecipient {
    final WindowManagerService mService;
    ......
    @Override
    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
            Rect outOutsets, InputChannel outInputChannel) {
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                outContentInsets, outStableInsets, outOutsets, outInputChannel);
    }
    ......
}

addWindow 方法首先调用 setUpdateInputWindowsNeededLw() 方法将 InputMonitor 类中的成员变量 mUpdateInputWindowsNeeded 置为 true,然后调用其 updateInputWindowsLw 方法。

WindowManagerService 类 addWindow

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    ......
    final InputMonitor mInputMonitor = new InputMonitor(this);
    ......
    public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            InputChannel outInputChannel) {
        ......
        synchronized(mWindowMap) {
            ......
            mInputMonitor.setUpdateInputWindowsNeededLw();
            ......
            // 更新当前焦点窗口
            if (focusChanged) {
                mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
            }
            mInputMonitor.updateInputWindowsLw(false /*force*/);
            ......
        }
        ......
    }
    ......
}

updateInputWindowsLw 中只要 force 和 mUpdateInputWindowsNeeded 有一个为 true,就会继续执行下面的代码,由于上一步设置了 mUpdateInputWindowsNeeded 为 true,因此一定会向下执行,所以接着就会运行 WindowManagerService 类成员变量 mInputManager 的 setInputWindows 方法。实际上就是调用 InputManagerService 类 setInputWindows 方法。
 

final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
    private final WindowManagerService mService;
    ......
    public void updateInputWindowsLw(boolean force) {
        if (!force && !mUpdateInputWindowsNeeded) {
            return;
        }
        mUpdateInputWindowsNeeded = false;
        ......
        mService.mInputManager.setInputWindows(mInputWindowHandles);
        ......
    }
    ......
}

 输入系统之 InputChannel 通信通道建立

Android 源码 输入系统之 InputChannel 通信通道建立-CSDN博客

InputChannel 通信得从 ViewRootImpl 类 setView 继续分析。输入通道(InputChannel)指定用于将输入事件发送到另一个进程中的窗口的文件描述符。它是可打包的,因此可以将其发送到接收事件的进程。每次只应该有一个线程从 InputChannel 中读取数据。

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;
                ......
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    // 创建客户端 InputChannel 对象
                    mInputChannel = new InputChannel();
                }
                try {
                    ......
                    // Binder 机制调用 Session 对象 addToDisplay 方法,注意入参包括 InputChannel 对象
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
                } catch (RemoteException e) {
                    ......
                } finally {
                    ......
                }
                ......
                if (mInputChannel != null) {
                    if (mInputQueueCallback != null) {
                        // 创建 InputQueue 对象
                        mInputQueue = new InputQueue();
                        mInputQueueCallback.onInputQueueCreated(mInputQueue);
                    }
                    // 接收输入事件,创建 WindowInputEventReceiver 对象
                    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
                }
                ......
            }
        }
    }
    ......
}

  1. 创建 InputChannel 对
  2. 将服务端 InputChannel 赋给服务端的 WindowState
  3. 将客户端 InputChannel 传递到 outInputChannel, 最终返回客户端应用进程
  4. 将服务端 InputChannel 注册到 InputDispatcher
public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    ......
    final InputMonitor mInputMonitor = new InputMonitor(this);
    ......
    public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            InputChannel outInputChannel) {
        ......
        synchronized(mWindowMap) {
            ......
            // WindowState 代表窗口管理器中的窗口。
            WindowState win = new WindowState(this, session, client, token,
                    attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
            ......
            if (outInputChannel != null && (attrs.inputFeatures
                    & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                String name = win.makeInputChannelName();
                // 创建 InputChannel 对
                InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
                // 将服务端 InputChannel 赋给服务端的 WindowState
                win.setInputChannel(inputChannels[0]);
                // 将客户端 InputChannel 传递到 outInputChannel, 最终返回客户端应用进程
                inputChannels[1].transferTo(outInputChannel);
                // 将服务端 InputChannel 注册到 InputDispatcher 
                mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
            }
            ......
        }
        ......
    }
    ......
}
public final class InputChannel implements Parcelable {
    ......
    private static native InputChannel[] nativeOpenInputChannelPair(String name);
    ......
    public static InputChannel[] openInputChannelPair(String name) {
        if (name == null) {
            throw new IllegalArgumentException("name must not be null");
        }

        if (DEBUG) {
            Slog.d(TAG, "Opening input channel pair '" + name + "'");
        }
        return nativeOpenInputChannelPair(name);
    }

    ......
}

不难看出 nativeOpenInputChannelPair 只是一个 jni 接口,实际工作由 jni native 层对应函数(android_view_InputChannel_nativeOpenInputChannelPair)完成。

name 转化(从 java String 对象转化为 C++ String8)
调用 Native InputChannel 对象 openInputChannelPair 方法
构建 NativeInputChannel 对象,并将 NativeInputChannel 对象转化为 Java InputChannel 对象返回
注意 Native InputChannel 对象和 NativeInputChannel 对象,前者为 C++ 类 InputChannel,后者为 C++ 类 NativeInputChannel。

NativeInputChannel 对象

frameworks/base/core/jni/android_view_InputChannel.cpp
 

static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
        jclass clazz, jstring nameObj) {
    const char* nameChars = env->GetStringUTFChars(nameObj, NULL);
    String8 name(nameChars);
    env->ReleaseStringUTFChars(nameObj, nameChars);

    sp<InputChannel> serverChannel;
    sp<InputChannel> clientChannel;
    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);

    if (result) {
        String8 message;
        message.appendFormat("Could not open input channel pair.  status=%d", result);
        jniThrowRuntimeException(env, message.string());
        return NULL;
    }

    jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
    if (env->ExceptionCheck()) {
        return NULL;
    }

    jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
            new NativeInputChannel(serverChannel));
    if (env->ExceptionCheck()) {
        return NULL;
    }

    jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
            new NativeInputChannel(clientChannel));
    if (env->ExceptionCheck()) {
        return NULL;
    }

    env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
    env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
    return channelPair;
}
status_t InputChannel::openInputChannelPair(const String8& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
        status_t result = -errno;
        ALOGE("channel '%s' ~ Could not create socket pair.  errno=%d",
                name.string(), 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));

    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;
}

将服务端 InputChannel 注册到 InputDispatcher

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    ......
    final InputMonitor mInputMonitor = new InputMonitor(this);
    ......
    public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            InputChannel outInputChannel) {
        ......
        synchronized(mWindowMap) {
            ......
            // WindowState 代表窗口管理器中的窗口。
            WindowState win = new WindowState(this, session, client, token,
                    attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
            ......
            if (outInputChannel != null && (attrs.inputFeatures
                    & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                String name = win.makeInputChannelName();
                // 创建 InputChannel 对
                InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
                // 将服务端 InputChannel 赋给服务端的 WindowState
                win.setInputChannel(inputChannels[0]);
                // 将客户端 InputChannel 传递到 outInputChannel, 最终返回客户端应用进程
                inputChannels[1].transferTo(outInputChannel);
                // 将服务端 InputChannel 注册到 InputDispatcher 
                mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
            }
            ......
        }
        ......
    }
    ......
}

public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
    ......
    private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
            InputWindowHandle inputWindowHandle, boolean monitor);
    ......
    public void registerInputChannel(InputChannel inputChannel,
            InputWindowHandle inputWindowHandle) {
        if (inputChannel == null) {
            throw new IllegalArgumentException("inputChannel must not be null.");
        }

        nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
    }
    ......
}

将 ptr 强转为 NativeInputManager 对象
将 inputChannelObj jobject 转化为 Native InputChannel 对象
将 inputWindowHandleObj jobject 转化为 Native InputWindowHandle 对象
调用 NativeInputManager 类 registerInputChannel 方法完成实际注册工作
 

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
        jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj);
    if (inputChannel == NULL) {
        throwInputChannelNotInitialized(env);
        return;
    }

    sp<InputWindowHandle> inputWindowHandle =
            android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);

    status_t status = im->registerInputChannel(
            env, inputChannel, inputWindowHandle, monitor);
    if (status) {
        String8 message;
        message.appendFormat("Failed to register input channel.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
        return;
    }
    ......
}

NativeInputManager 类 registerInputChannel 方法最终调用 InputDispatcher 类的 registerInputChannel 完成真正的注册。

InputDispatcher 类的 registerInputChannel

status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
        const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
    return mInputManager->getDispatcher()->registerInputChannel(
            inputChannel, inputWindowHandle, monitor);
}

InputDispatcher::registerInputChannel

检查 InputChannel 是否已经注册过
创建 Connection 对象,他表示客户端和服务端的一个输入数据通道
以 fd 为 key 将 Connection 添加到容器(mConnectionsByFd)中
将 fd 添加到 Looper 监听列表中。一旦对端的 Socket 写入数据,Looper 就会被唤醒,接着就会调用 handleReceiveCallback
 

status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
    ......
    { // acquire lock
        AutoMutex _l(mLock);
        // 进入此 case 表示 inputChannel 已经注册过了
        if (getConnectionIndexLocked(inputChannel) >= 0) {
            ALOGW("Attempted to register already registered input channel '%s'",
                    inputChannel->getName().string());
            return BAD_VALUE;
        }
        // Connection 表示客户端和服务端的一个输入数据通道
        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
        // 获取 socketpair fd
        int fd = inputChannel->getFd();
        // 以 fd 为 key 将 Connection 添加到容器中
        mConnectionsByFd.add(fd, connection);
        ......
        // 将 fd 添加到 Looper 监听列表中,一旦对端的 socket 写入数据,Looper 就会被唤醒
        // 接着就会调用 handleReceiveCallback
        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
    } // release lock

    // 唤醒 Looper,因为一些连接(Connection)已经改变
    mLooper->wake();
    return OK;
}

代码走到这里,InputDispatcher 就和 InputChannel 建立了关联。现在是时候回到 ViewRootImpl setView 方法中具体分析如何关联客户端 InputChannel。

创建 WindowInputEventReceiver 对象

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    final class WindowInputEventReceiver extends InputEventReceiver {
        public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }

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

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

        @Override
        public void dispose() {
            unscheduleConsumeBatchedInput();
            super.dispose();
        }
    }
    ......
}
public abstract class InputEventReceiver {
    ......
    public InputEventReceiver(InputChannel inputChannel, Looper looper) {
        if (inputChannel == null) {
            throw new IllegalArgumentException("inputChannel must not be null");
        }
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }

        mInputChannel = inputChannel;
        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                inputChannel, mMessageQueue);

        mCloseGuard.open("dispose");
    }
    ......
}
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject inputChannelObj, jobject messageQueueObj) {
    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj);
    if (inputChannel == NULL) {
        jniThrowRuntimeException(env, "InputChannel is not initialized.");
        return 0;
    }

    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
            receiverWeak, inputChannel, messageQueue);
    status_t status = receiver->initialize();
    if (status) {
        String8 message;
        message.appendFormat("Failed to initialize input event receiver.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
        return 0;
    }

    receiver->incStrong(gInputEventReceiverClassInfo.clazz); // 保留对象的引用
    return reinterpret_cast<jlong>(receiver.get());
}

NativeInputEventReceiver 构造函数

NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
        jobject receiverWeak, const sp<InputChannel>& inputChannel,
        const sp<MessageQueue>& messageQueue) :
        mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
        mInputConsumer(inputChannel), mMessageQueue(messageQueue),
        mBatchedInputEventPending(false), mFdEvents(0) {
    if (kDebugDispatchCycle) {
        ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
    }
}



status_t NativeInputEventReceiver::initialize() {
    setFdEvents(ALOOPER_EVENT_INPUT);
    return OK;
}

由于 mFdEvents 初始化为 0, ALOOPER_EVENT_INPUT = 1 << 0,因此会赋值 mFdEvents = ALOOPER_EVENT_INPUT。然后取出 socket fd,就会向客户端 Looper 添加 fd 描述符,当有数据从服务端写入,就会唤醒 Looper。最终回调 NativeInputEventReceiver 的 handleEvent 方法。

void NativeInputEventReceiver::setFdEvents(int events) {
    if (mFdEvents != events) {
        mFdEvents = events;
        int fd = mInputConsumer.getChannel()->getFd();
        if (events) {
            mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
        } else {
            mMessageQueue->getLooper()->removeFd(fd);
        }
    }
}

输入系统之事件窗口分发

Android 源码 输入系统之事件窗口分发_handlereceivecallback-CSDN博客

NativeInputEventReceiver 类 handleEvent 被调用,用来处理 InputDispatcher 发送来的事件。 InputDispatcher 和输入窗口之间双向的通道,这是通过 InputChannel 承载的。现在可以继续分析从 InputDispatcher 发送出的事件如何被接收处理了。

NativeInputEventReceiver 类 handleEvent

int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    ......
    if (events & ALOOPER_EVENT_INPUT) {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
        return status == OK || status == NO_MEMORY ? 1 : 0;
    }
    ......
    return 1;
}

 调用 InputConsumer 类 consume 方法接收输入事件(InputEvent)
调用 android_view_KeyEvent_fromNative 将 InputEvent 转化为 jobject 供 Java 层使用
Native 调用 Java InputEventReceiver 类 dispatchInputEvent 方法转入 Java 层处理
 

frameworks/base/core/jni/android_view_InputEventReceiver.cpp

status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
    ......
    bool skipCallbacks = false;
    for (;;) {
        uint32_t seq;
        InputEvent* inputEvent;
        status_t status = mInputConsumer.consume(&mInputEventFactory,
                consumeBatches, frameTime, &seq, &inputEvent);
        ......
        if (!skipCallbacks) {
            if (!receiverObj.get()) {
                receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
                if (!receiverObj.get()) {
                    ALOGW("channel '%s' ~ Receiver object was finalized "
                            "without being disposed.", getInputChannelName());
                    return DEAD_OBJECT;
                }
            }
            ......
            jobject inputEventObj;
            switch (inputEvent->getType()) {
            case AINPUT_EVENT_TYPE_KEY:
                ......
                inputEventObj = android_view_KeyEvent_fromNative(env,
                        static_cast<KeyEvent*>(inputEvent));
                break;

            case AINPUT_EVENT_TYPE_MOTION: {
                ......
                break;
            }

            default:
                assert(false); // InputConsumer should prevent this from ever happening
                inputEventObj = NULL;
            }

            if (inputEventObj) {
                ......
                env->CallVoidMethod(receiverObj.get(),
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
                if (env->ExceptionCheck()) {
                    ALOGE("Exception dispatching input event.");
                    skipCallbacks = true;
                }
                env->DeleteLocalRef(inputEventObj);
            } else {
                ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
                skipCallbacks = true;
            }
        }

        if (skipCallbacks) {
            mInputConsumer.sendFinishedSignal(seq, false);
        }
    }
}
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
        bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
    ......
    *outSeq = 0;
    *outEvent = NULL;
    // 获取下一条输入消息。
    while (!*outEvent) {
        if (mMsgDeferred) {
            ......
        } else {
            // 收到新消息。
//InputConsumer 成员变量 mChannel(InputChannel)调用 receiveMessage 接收消息,
//最终会使用 sys/socket.h 头文件中定义的 recv 方法。
            status_t result = mChannel->receiveMessage(&mMsg);
            ......
        }

        switch (mMsg.header.type) {
        case InputMessage::TYPE_KEY: {
            KeyEvent* keyEvent = factory->createKeyEvent();
            if (!keyEvent) return NO_MEMORY;
            // 将 InputMessage 转化为 KeyEvent
            initializeKeyEvent(keyEvent, &mMsg);
            *outSeq = mMsg.body.key.seq;
            *outEvent = keyEvent;
            ......
            break;
        }

        case AINPUT_EVENT_TYPE_MOTION: {
            ......
        }

        default:
            ALOGE("channel '%s' consumer ~ Received unexpected message of type %d",
                    mChannel->getName().string(), mMsg.header.type);
            return UNKNOWN_ERROR;
        }
    }
    return OK;
}
status_t InputChannel::receiveMessage(InputMessage* msg) {
    ssize_t nRead;
    do {
        nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
    } while (nRead == -1 && errno == EINTR);

    if (nRead < 0) {
        int error = errno;
        ......
        if (error == EAGAIN || error == EWOULDBLOCK) {
            return WOULD_BLOCK;
        }
        if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {
            return DEAD_OBJECT;
        }
        return -error;
    }

    if (nRead == 0) { // check for EOF
        ......
        return DEAD_OBJECT;
    }

    if (!msg->isValid(nRead)) {
        ......
        return BAD_VALUE;
    }
    ......
    return OK;
}

void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) {
    event->initialize(
            msg->body.key.deviceId,
            msg->body.key.source,
            msg->body.key.action,
            msg->body.key.flags,
            msg->body.key.keyCode,
            msg->body.key.scanCode,
            msg->body.key.metaState,
            msg->body.key.repeatCount,
            msg->body.key.downTime,
            msg->body.key.eventTime);
}

 Native 调用 Java InputEventReceiver 类 dispatchInputEvent 方法转入 Java 层处理。实际调用 Java 类 WindowInputEventReceiver dispatchInputEvent 方法。NativeInputEventReceiver 对象时传递来一个弱引用(WindowInputEventReceiver),然后将其提升为全局引用赋值给了 mReceiverWeakGlobal。Native CallVoidMethod 调用的时候派上了用场。

InputEventReceiver 类 dispatchInputEvent

public abstract class InputEventReceiver {
    ......
    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchInputEvent(int seq, InputEvent event) {
        mSeqMap.put(event.getSequenceNumber(), seq);
        onInputEvent(event);
    }
    ......
}
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    final class WindowInputEventReceiver extends InputEventReceiver {
        public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }

        @Override
        public void onInputEvent(InputEvent event) {
            enqueueInputEvent(event, this, 0, true);
        }
        ......
    }
    ......
}
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    void enqueueInputEvent(InputEvent event,
            InputEventReceiver receiver, int flags, boolean processImmediately) {
        adjustInputEventForCompatibility(event);
        // 获取 QueuedInputEvent 对象
        QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);

        // 始终按顺序将输入事件排入队列,而不考虑其时间戳。
        QueuedInputEvent last = mPendingInputEventTail;
        if (last == null) {
            mPendingInputEventHead = q;
            mPendingInputEventTail = q;
        } else {
            last.mNext = q;
            mPendingInputEventTail = q;
        }
        // 未处理的输入事件计数
        mPendingInputEventCount += 1;
        Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
                mPendingInputEventCount);
        // 此处 processImmediately 为 true
        if (processImmediately) {
            doProcessInputEvents();
        } else {
            scheduleProcessInputEvents();
        }
    }
    ......
}
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    void doProcessInputEvents() {
        // 在队列中传递所有未处理的输入事件。
        while (mPendingInputEventHead != null) {
            QueuedInputEvent q = mPendingInputEventHead;
            mPendingInputEventHead = q.mNext;
            if (mPendingInputEventHead == null) {
                mPendingInputEventTail = null;
            }
            q.mNext = null;

            mPendingInputEventCount -= 1;
            Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
                    mPendingInputEventCount);

            long eventTime = q.mEvent.getEventTimeNano();
            long oldestEventTime = eventTime;
            ......
            deliverInputEvent(q);
        }

        // 我们已经处理完所有现在可以处理的输入事件,因此我们可以立即清除待处理标志。
        if (mProcessInputEventsScheduled) {
            mProcessInputEventsScheduled = false;
            mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
        }
    }
    ......
}
public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    private void deliverInputEvent(QueuedInputEvent q) {
        ......
        InputStage stage;
        if (q.shouldSendToSynthesizer()) {
            stage = mSyntheticInputStage;
        } else {
            stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
        }

        if (stage != null) {
            stage.deliver(q);
        } else {
            finishInputEvent(q);
        }
    }
    ......
}

mSyntheticInputStage、mFirstPostImeInputStage 和 mFirstInputStage 这三个成员变量都是在 ViewRootImpl 类 setView 方法中赋值的。

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                ......
                // 设置输入管道。
                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;
                ......
            }
        }
    }
    ......
}

InputStage —— 基类,用于实现责任链中处理输入事件的 Stage。事件通过 deliver 方法传递到 Stage 上。然后,该 Stage 可以选择完成事件或将其转发到下一个 Stage。

SyntheticInputStage —— 从未处理的输入事件执行新输入事件的合成。

ViewPostImeInputStage —— 将 post-ime 输入事件传递到视图层次结构。

AsyncInputStage —— 用于实现支持异步和无序处理输入事件的输入管道 Stage 的基类。除了正常的 InputStage 可以做的事情之外,异步 InputStage 还可以延迟已经交付给它的输入事件,并稍后完成或转发它。

NativePostImeInputStage —— 将 post-ime 输入事件传递到 Native Activity。

EarlyPostImeInputStage —— 执行 post-ime 输入事件的早期处理。

ImeInputStage —— 向 ime 交付输入事件。不支持指针事件。

ViewPreImeInputStage —— 将 pre-ime 输入事件交付给视图层次结构。不支持指针事件。

NativePreImeInputStage —— 将 pre-ime 输入事件交付给 Native Activity。不支持指针事件

processKeyEvent 函数

View dispatchKeyEvent 方法

onProcess 方法判断是否为按键事件然后交由 processKeyEvent 进一步处理。processKeyEvent 函数中调用了相应 View 的 dispatchKeyEvent 方法,进行事件分发,这就把输入事件派发到了当前窗口了!

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    final class ViewPostImeInputStage extends InputStage {
        public ViewPostImeInputStage(InputStage next) {
            super(next);
        }

        @Override
        protected int onProcess(QueuedInputEvent q) {
            if (q.mEvent instanceof KeyEvent) {
                return processKeyEvent(q);
            } else {
                ......
            }
        }

        @Override
        protected void onDeliverToNext(QueuedInputEvent q) {
            ......
            super.onDeliverToNext(q);
        }

        private int processKeyEvent(QueuedInputEvent q) {
            final KeyEvent event = (KeyEvent)q.mEvent;
            ......
            // 将按键交付给视图层次结构。
            if (mView.dispatchKeyEvent(event)) {
                return FINISH_HANDLED;
            }
            // 是否需要删除输入事件
            if (shouldDropInputEvent(q)) {
                return FINISH_NOT_HANDLED;
            }

            // 快捷键处理
            if (event.getAction() == KeyEvent.ACTION_DOWN
                    && event.isCtrlPressed()
                    && event.getRepeatCount() == 0
                    && !KeyEvent.isModifierKey(event.getKeyCode())) {
                if (mView.dispatchKeyShortcutEvent(event)) {
                    return FINISH_HANDLED;
                }
                if (shouldDropInputEvent(q)) {
                    return FINISH_NOT_HANDLED;
                }
            }

            // 应用回退事件策略。
            if (mFallbackEventHandler.dispatchKeyEvent(event)) {
                return FINISH_HANDLED;
            }
            if (shouldDropInputEvent(q)) {
                return FINISH_NOT_HANDLED;
            }

            // 处理自动焦点更改。
            if (event.getAction() == KeyEvent.ACTION_DOWN) {
                int direction = 0;
                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_DPAD_LEFT:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_LEFT;
                        }
                        break;
                    case KeyEvent.KEYCODE_DPAD_RIGHT:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_RIGHT;
                        }
                        break;
                    case KeyEvent.KEYCODE_DPAD_UP:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_UP;
                        }
                        break;
                    case KeyEvent.KEYCODE_DPAD_DOWN:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_DOWN;
                        }
                        break;
                    case KeyEvent.KEYCODE_TAB:
                        if (event.hasNoModifiers()) {
                            direction = View.FOCUS_FORWARD;
                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
                            direction = View.FOCUS_BACKWARD;
                        }
                        break;
                }
                if (direction != 0) {
                    View focused = mView.findFocus();
                    if (focused != null) {
                        View v = focused.focusSearch(direction);
                        if (v != null && v != focused) {
                            // 进行数学运算,将先前关注的焦点区域变成新焦点的视图坐标系
                            focused.getFocusedRect(mTempRect);
                            if (mView instanceof ViewGroup) {
                                ((ViewGroup) mView).offsetDescendantRectToMyCoords(
                                        focused, mTempRect);
                                ((ViewGroup) mView).offsetRectIntoDescendantCoords(
                                        v, mTempRect);
                            }
                            if (v.requestFocus(direction, mTempRect)) {
                                // 播放音效
                                playSoundEffect(SoundEffectConstants
                                        .getContantForFocusDirection(direction));
                                return FINISH_HANDLED;
                            }
                        }

                        // 给焦点视图最后一次机会来处理 dpad 键。
                        if (mView.dispatchUnhandledMove(focused, direction)) {
                            return FINISH_HANDLED;
                        }
                    } else {
                        View v = focusSearch(null, direction);
                        if (v != null && v.requestFocus(direction)) {
                            return FINISH_HANDLED;
                        }
                    }
                }
            }
            return FORWARD;
        }
        ......
    }
    ......
}

 输入按键事件处理完成以后就会调用 ViewRootImpl 类的 finishInputEvent 方法。

QueuedInputEvent 类的成员变量 mReceiver 是在 enqueueInputEvent 方法中调用 obtainQueuedInputEvent 函数传入的 WindowInputEventReceiver 对象。事件已经处理完成,所以 handled = true,接着就会调用 WindowInputEventReceiver 类 finishInputEvent 方法,此方法实现在其父类 InputEventReceiver 中。

finishInputEvent 方法

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    ......
    private void finishInputEvent(QueuedInputEvent q) {
        ......
        if (q.mReceiver != null) {
            boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
            q.mReceiver.finishInputEvent(q.mEvent, handled);
        } else {
            ......
        }

        recycleQueuedInputEvent(q);
    }
    ......
}
public abstract class InputEventReceiver {
    ......
    private static native void nativeFinishInputEvent(long receiverPtr, int seq, boolean handled);
    ......
    public final void finishInputEvent(InputEvent event, boolean handled) {
        if (event == null) {
            throw new IllegalArgumentException("event must not be null");
        }
        if (mReceiverPtr == 0) {
            Log.w(TAG, "Attempted to finish an input event but the input event "
                    + "receiver has already been disposed.");
        } else {
            int index = mSeqMap.indexOfKey(event.getSequenceNumber());
            if (index < 0) {
                Log.w(TAG, "Attempted to finish an input event that is not in progress.");
            } else {
                int seq = mSeqMap.valueAt(index);
                mSeqMap.removeAt(index);
                // 重点关注
                nativeFinishInputEvent(mReceiverPtr, seq, handled);
            }
        }
        event.recycleIfNeededAfterDispatch();
    }
    ......
}
static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
        jint seq, jboolean handled) {
    sp<NativeInputEventReceiver> receiver =
            reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
    status_t status = receiver->finishInputEvent(seq, handled);
    if (status && status != DEAD_OBJECT) {
        String8 message;
        message.appendFormat("Failed to finish input event.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
    }
}

InputConsumer 类 sendFinishedSignal 发送完成信号

status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
    ......
    status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
    ......
    return status;
}
 

status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
    ......
    size_t seqChainCount = mSeqChains.size();
    // 首先发送批序列链的完成信号。
    if (seqChainCount) {
        uint32_t currentSeq = seq;
        uint32_t chainSeqs[seqChainCount];
        size_t chainIndex = 0;
        for (size_t i = seqChainCount; i-- > 0; ) {
             const SeqChain& seqChain = mSeqChains.itemAt(i);
             if (seqChain.seq == currentSeq) {
                 currentSeq = seqChain.chain;
                 chainSeqs[chainIndex++] = currentSeq;
                 mSeqChains.removeAt(i);
             }
        }
        status_t status = OK;
        while (!status && chainIndex-- > 0) {
            status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
        }
        if (status) {
            // 一个错误发生了,所以至少有一个信号没有发送,重建链。
            do {
                SeqChain seqChain;
                seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
                seqChain.chain = chainSeqs[chainIndex];
                mSeqChains.push(seqChain);
            } while (chainIndex-- > 0);
            return status;
        }
    }

    // 发送批处理中的最后一条消息的完成信号。
    return sendUnchainedFinishedSignal(seq, handled);
}




status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
    InputMessage msg;
    msg.header.type = InputMessage::TYPE_FINISHED;
    msg.body.finished.seq = seq;
    msg.body.finished.handled = handled;
    return mChannel->sendMessage(&msg);
}

由于客户端 Socket 写入数据,Looper 被唤醒就会执行 InputDispatcher 类 handleReceiveCallback 方法。

mConnectionsByFd 取出 Connection
调用 Connection 类成员变量 inputPublisher 的 receiveFinishedSignal 方法接收消息
调用 InputDispatcher 类 finishDispatchCycleLocked 方法
调用 runCommandsLockedInterruptible 执行命令(Commond)

InputDispatcher::handleReceiveCallback

int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
    InputDispatcher* d = static_cast<InputDispatcher*>(data);

    { // acquire lock
        AutoMutex _l(d->mLock);

        ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
        if (connectionIndex < 0) {
            ALOGE("Received spurious receive callback for unknown input channel.  "
                    "fd=%d, events=0x%x", fd, events);
            return 0; // remove the callback
        }

        bool notify;
        sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
        if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
            if (!(events & ALOOPER_EVENT_INPUT)) {
                ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
                        "events=0x%x", connection->getInputChannelName(), events);
                return 1;
            }

            nsecs_t currentTime = now();
            bool gotOne = false;
            status_t status;
            for (;;) {
                uint32_t seq;
                bool handled;
                status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
                if (status) {
                    break;
                }
                d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
                gotOne = true;
            }
            if (gotOne) {
                d->runCommandsLockedInterruptible();
                if (status == WOULD_BLOCK) {
                    return 1;
                }
            }
            ......
        } else {
            ......
        }
        ......
    } // release lock
}

服务端 InputChannel 读取发来的消息

status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {
    ......
    InputMessage msg;
    status_t result = mChannel->receiveMessage(&msg);
    if (result) {
        *outSeq = 0;
        *outHandled = false;
        return result;
    }
    if (msg.header.type != InputMessage::TYPE_FINISHED) {
        ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer",
                mChannel->getName().string(), msg.header.type);
        return UNKNOWN_ERROR;
    }
    *outSeq = msg.body.finished.seq;
    *outHandled = msg.body.finished.handled;
    return OK;
}

finishDispatchCycleLocked 方法中调用 onDispatchCycleFinishedLocked。

void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
        const sp<Connection>& connection, uint32_t seq, bool handled) {
    ......
    connection->inputPublisherBlocked = false;

    if (connection->status == Connection::STATUS_BROKEN
            || connection->status == Connection::STATUS_ZOMBIE) {
        return;
    }

    // 通知其他系统组件并准备开始下一个调度周期。
    onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
}



void InputDispatcher::onDispatchCycleFinishedLocked(
        nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
    CommandEntry* commandEntry = postCommandLocked(
            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
    commandEntry->connection = connection;
    commandEntry->eventTime = currentTime;
    commandEntry->seq = seq;
    commandEntry->handled = handled;
}

调用 postCommandLocked 方法,其入参是个函数指针

InputDispatcher::doDispatchCycleFinishedLockedInterruptible。然后将返回的 CommandEntry 对应成员变量赋值。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值