Android 12 Input系统理解
参考文献:
Input系统—启动篇
Input系统—InputReader线程
Input系统—InputDispatcher线程
Input系统—UI线程
Input系统—事件处理全过程
一、Input系统-事件处理过程
frameworks/native/services/inputflinger/
- InputDispatcher.cpp
- InputReader.cpp
- InputManager.cpp
- EventHub.cpp
- InputListener.cpp
frameworks/native/libs/input/
- InputTransport.cpp
- Input.cpp
- InputDevice.cpp
- Keyboard.cpp
- KeyCharacterMap.cpp
- IInputFlinger.cpp
frameworks/base/services/core/
- java/com/android/server/input/InputManagerService.java
- jni/com_android_server_input_InputManagerService.cpp
1. Input系统—概述
用户触摸屏幕(TP)或者物理按键,触发的是硬件驱动。驱动将事件写入到输入设备节点;接着输入系统将设备节点经过每一层封装后,成为KeyEvent或者MotionEvent;最后,给到对应窗口(Window)消费该事件。
Input模块主要组成:
- Native层的InputReader负责从EventHub取出事件并处理,再交给InputDispatcher
- Native层的InputDispatcher接收来自InputReader的输入事件,并记录WMS的窗口信息,用于派发事件到合适的窗口
- Java层的InputManagerService跟WMS交互,WMS记录所有窗口信息,并同步更新到IMS,为InputDispatcher正确派发事件到ViewRootImpl提供保障
Input相关动态库:
- libinputflinger.so:frameworks/native/services/inputflinger/
- libinputservice.so:frameworks/base/libs/input/
- libinput.so: frameworks/native/libs/input/
2.Input系统—启动过程
frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
frameworks/native/services/inputflinger/InputManager.cpp
#SystemServer.java
├──startOtherServices()
└──inputManager = new InputManagerService(context, mActivityManagerService);//InputManagerService初始化
| #InputManagerService.java
| └──mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
| #com_android_server_input_InputManagerService.cpp
| ├──nativeInit(JNIEnv* env, jclass /* clazz */,jobject serviceObj, jobject contextObj, jobject messageQueueObj)
| └──NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());
| └──InputManager* im = new InputManager(this, this);
| #InputManager.cpp
| └──mDispatcher = createInputDispatcher(dispatcherPolicy);//创建InputDispatcher对象
| └──mClassifier = new InputClassifier(mDispatcher);//创建InputClassifier对象
| └──mReader = createInputReader(readerPolicy, mClassifier);//创建InputReader对象
└──inputManager.start();
#com_android_server_input_InputManagerService.cpp
└──nativeStart(mPtr);
#InputManager.cpp
├──nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr)
└──status_t result = mDispatcher->start();
└──result = mReader->start();
2.1#SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...
inputManager = new InputManagerService(context, mActivityManagerService);//创建InputManagerService对象
...
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);//将InputManagerService与WindowManagerService绑定
...
ServiceManager.addService(Context.INPUT_SERVICE, inputManager, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
...
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());//设置Input回调
inputManager.start();//启动Input系统
}
2.2#InputManagerService.java
public InputManagerService(Context context, ActivityManagerService ams) {
...
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());//运行在线程"android.display"
...
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
...
}
2.3#nativeInit
<-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);//获取native消息队列
...
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());
im->incStrong(0);
eturn reinterpret_cast<jlong>(im);
}
2.4#NativeInputManager
<-com_android_server_input_InputManagerService.cpp>
NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :mLooper(looper), mInteractive(true) {
...
mServiceObj = env->NewGlobalRef(serviceObj);//上层IMS对象
...
InputManager* im = new InputManager(this, this);// 创建InputManager对象
...
}
2.5#InputManager
<-InputManager.cpp>
InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = createInputDispatcher(dispatcherPolicy);
mClassifier = new InputClassifier(mDispatcher);
mReader = createInputReader(readerPolicy, mClassifier);
}
2.6#InputDispatcher
<-InputDispatcher.cpp>
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
: mPolicy(policy),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
mAppSwitchSawKeyDown(false),
mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(nullptr),
mDispatchEnabled(false),
mDispatchFrozen(false),
mInputFilterEnabled(false),
// mInTouchMode will be initialized by the WindowManager to the default device config.
// To avoid leaking stack in case that call never comes, and for tests,
// initialize it here anyways.
mInTouchMode(true),
mMaximumObscuringOpacityForTouch(1.0f),
mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
mWindowTokenWithPointerCapture(nullptr),
mLatencyAggregator(),
mLatencyTracker(&mLatencyAggregator),
mCompatService(getCompatService()) {
mLooper = new Looper(false);//创建Looper对象
mReporter = createInputReporter();//创建InputReporter对象
mKeyRepeatState.lastKeyEntry = nullptr;
policy->getDispatcherConfiguration(&mConfig);//获取分发超时参数
}
该方法主要工作:
- 创建属于自己线程的Looper对象;
- 超时参数来自于IMS,参数默认值keyRepeatTimeout = 500,keyRepeatDelay = 50
2.7#InputReader
<-InputReader.cpp>
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
mGlobalMetaState(0),
mLedMetaState(AMETA_NUM_LOCK_ON),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
mQueuedListener = new QueuedInputListener(listener);//创建输入监听对象
{ // acquire lock
std::scoped_lock _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
2.8#IMS.start()
<-InputManagerService.java>
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
registerPointerSpeedSettingObserver();//注册触摸点速度观察者
registerShowTouchesSettingObserver();//注册是否显示功能的观察者
registerAccessibilityLargePointerSettingObserver();
registerLongPressTimeoutObserver();
registerMaximumObscuringOpacityForTouchSettingObserver();
registerBlockUntrustedTouchesModeSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("user switched");
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
updatePointerSpeedFromSettings();//更新触摸点的速度
updateShowTouchesFromSettings();//更新是否在屏幕上显示触摸点状态
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("just booted");
updateMaximumObscuringOpacityForTouchFromSettings();
updateBlockUntrustedTouchesModeFromSettings();
}
2.8#nativeStart
<-com_android_server_input_InputManagerService.cpp>
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
status_t result = im->getInputManager()->start();//调用InputManager.cpp中start()
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
2.9#InputManager.start
<-InputManager.cpp>
status_t InputManager::start() {
status_t result = mDispatcher->start();//启动InputDispatcher线程
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReader->start();//启动InputReader线程
if (result) {
ALOGE("Could not start InputReader due to error %d.", result);
mDispatcher->stop();
return result;
}
return OK;//“OK”代表成功,启动成功
}
3. Input系统—InputReader线程
frameworks/native/services/inputflinger/reader/InputReader.cpp
frameworks/native/services/inputflinger/reader/EventHub.cpp
frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
frameworks/native/services/inputflinger/reader/InputDevice.cpp
frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
frameworks/native/services/inputflinger/InputListener.cpp
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
system/core/libutils/Looper.cpp
#InputReader.cpp
├──start()
└──mThread = std::make_unique<InputThread>( "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
└──loopOnce()
| └──size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
| | #EventHub.cpp
| | ├──getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize)//通过EventHub(监听目录/dev/input)读取事件放入mEventBuffer, 再将事件input_event转换为RawEvent
| | └──scanDevicesLocked()
| | └──scanDirLocked(const std::string& dirname)
| | └──openDeviceLocked(const std::string& devicePath)
| | └──addDeviceLocked(std::unique_ptr<Device> device)
| └──processEventsLocked(mEventBuffer, count);//对事件进行加工, 转换RawEvent -> NotifyKeyArgs(NotifyArgs)
| | └──if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT)
| | | └──processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,size_t count)
| | | └──device->process(rawEvents, count);
| | | #InputDevice.cpp
| | | ├──process(const RawEvent* rawEvents, size_t count)
| | | └──mapper.process(rawEvent);//列举KeyboardInputMapper作为例子
| | | #KeyboardInputMapper.cpp
| | | ├──process(const RawEvent* rawEvent)
| | | └──processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,int32_t usageCode)
| | | └──getListener()->notifyKey(&args);
| | | #InputListener.cpp
| | | ├──notifyKey(const NotifyKeyArgs* args)
| | | └──mArgsQueue.push_back(new NotifyKeyArgs(*args));
| | └──else
| | └──addDeviceLocked(rawEvent->when, rawEvent->deviceId);
| | └──std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
| | └──device->addEventHubDevice(eventHubId);
| | #InputDevice.cpp
| | ├──addEventHubDevice(int32_t eventHubId, bool populateMappers)
| | └──添加各类输入设备
| └──mQueuedListener->flush();//将事件发送到InputDispatcher线程
| #InputListener.cpp
| ├──flush()
| └──notify(const sp<InputListenerInterface>& listener)
| └──listener->notifyKey(this);
| #InputDispatcher.cpp
| ├──notifyKey(const NotifyKeyArgs* args)
| └──mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
| | #com_android_server_input_InputManagerService.cpp
| | ├──interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags)
| | └── wmActions = env->CallIntMethod(mServiceObj,gServiceClassInfo.interceptKeyBeforeQueueing, keyEventObj, policyFlags);
| └──mPolicy->filterInputEvent(&event, policyFlags)
| | #com_android_server_input_InputManagerService.cpp
| | ├──filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags)
| | └── jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,//当inputEventObj不为空,则调用Java层的IMS.filterInputEvent()
| └──needWake = enqueueInboundEventLocked(std::move(newEntry));
| | #InputDispatcher.cpp
| | ├──enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry)
| | └──shouldPruneInboundQueueLocked(const MotionEntry& motionEntry)
| | └──sp<InputWindowHandle> touchedWindowHandle =findTouchedWindowAtLocked(displayId, x, y, nullptr);//查询触摸的窗口
| | └──std::vector<TouchedMonitor> gestureMonitors = findTouchedGestureMonitorsLocked(displayId, {});//查询可触摸的手势
| └──mLooper->wake();//唤起InputDispatcher线程
| #Looper.cpp
| ├──wake()
| └──ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));
└──mEventHub->wake(); //唤起EventHub
#EventHub.cpp
├──wake()
└──nWrite = write(mWakeWritePipeFd, "W", 1);
3.1#start()
<-InputReader.cpp>
status_t InputReader::start() {
if (mThread) {//mThread不为空,InputReader已存在
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
3.2#loopOnce()
<-InputReader.cpp>
void InputReader::loopOnce() {
...
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);//从EventHub读取事件,其中EVENT_BUFFER_SIZE = 256
{ // acquire lock
std::scoped_lock _l(mLock);
mReaderIsAliveCondition.notify_all();
if (count) {
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;
inputDevices = getInputDevicesLocked();
}
} // release lock
...
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {//输入设备发生改变
mPolicy->notifyInputDevicesChanged(inputDevices);
}
mQueuedListener->flush();//发送事件到InputDispatcher
}
3.2#getEvents()
<-EventHub.cpp>
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
...
for (;;) {
...
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked();//扫描设备
mNeedToSendFinishedDeviceScan = true;
}
...
while (mPendingEventIndex < mPendingEventCount) {
...
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];//从mPendingEventItems读取事件项
...
if (eventItem.data.fd == mWakeReadPipeFd) {
if (eventItem.events & EPOLLIN) {
ALOGV("awoken after wake()");
awoken = true;
char wakeReadBuffer[16];
ssize_t nRead;
do {
nRead = read(mWakeReadPipeFd, wakeReadBuffer, sizeof(wakeReadBuffer));//从wakeReadBuffer中读取事件
} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(wakeReadBuffer));
} else {
ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
eventItem.events);
}
continue;
}
...
// This must be an input event
if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity); //从设备不断读取事件,放入到readBuffer
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// Device was removed before INotify noticed.
deviceChanged = true;
closeDeviceLocked(*device);
}
...
}else{
int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
size_t count = size_t(readSize) / sizeof(struct input_event);
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];//获取readBuffer的数据
event->when = processEventTimestamp(iev);//将input_event信息, 封装成RawEvent
event->readTime = systemTime(SYSTEM_TIME_MONOTONIC);
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
}
if (capacity == 0) {
// The result buffer is full. Reset the pending event index
// so we will try to read the device again on the next iteration.
mPendingEventIndex -= 1;
break;
}
}
...
}
...
}
...
mLock.unlock(); // release lock before poll
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);//等待input事件的到来
mLock.lock(); // reacquire lock after poll
...
}
...
return event - buffer; //返回所读取的事件个数
}
EventHub采用INotify + epoll机制实现监听目录/dev/input下的设备节点。
3.3设备扫描
<-EventHub.cpp>
void EventHub::scanDevicesLocked() {
status_t result = scanDirLocked(DEVICE_PATH);//DEVICE_PATH="/dev/input"
if (result < 0) {
ALOGE("scan dir failed for %s", DEVICE_PATH);
}
if (isV4lScanningEnabled()) {
result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
if (result != OK) {
ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
}
}
if (mDevices.find(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) == mDevices.end()) {
createVirtualKeyboardLocked();
}
}
status_t EventHub::scanDirLocked(const std::string& dirname) {
for (const auto& entry : std::filesystem::directory_iterator(dirname)) {//读取/dev/input/目录下所有的设备节点
openDeviceLocked(entry.path());//打开相应的设备节点
}
return 0;
}
void EventHub::openDeviceLocked(const std::string& devicePath) {
...
int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);//打开设备文件
InputDeviceIdentifier identifier;
//获取设备名称
if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.name = buffer;
}
...
// Get device identifier.
struct input_id inputId;
if (ioctl(fd, EVIOCGID, &inputId)) {
ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return;
}
identifier.bus = inputId.bustype;
identifier.product = inputId.product;
identifier.vendor = inputId.vendor;
identifier.version = inputId.version;
// Get device physical location.
if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
// fprintf(stderr, "could not get location for %s, %s\n", devic