总体图:
原文链接: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 中的相应事件也需要进一步了解
输入系统之窗口关联
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 方法,奥秘就在这里!
- 获取 Window 和 DecorView 对象;
- 设置 DecorView 为不可见;
- 获取 WindowManager 对象;
- 将 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); } ...... }
- 创建 ViewRootImpl 对象;
- 调用 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) { ...... } } ...... }
- 创建 InputChannel 对象;
- 远程调用 Session addToDisplay 方法;
- 创建接收输入事件者 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()); } ...... } } } ...... }
- 创建 InputChannel 对
- 将服务端 InputChannel 赋给服务端的 WindowState
- 将客户端 InputChannel 传递到 outInputChannel, 最终返回客户端应用进程
- 将服务端 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 对应成员变量赋值。