一:概述
Android是由事件驱动的,当用户点击屏幕时,首先TP驱动识别到点击屏幕点击事件,写入"dev/input"节点,输入系统识别到"dev/input"有新的事件,会把事件进行封装,传递给对应的View进行事件处理。由此可见,事件的获取、传递、分发都是由输入系统来完成,输入系统的重要性不言而喻。下面根据AndroidV的代码来剖析输入系统。
二:输入系统简介
Input系统中很重要的几个类:InputManagerService、InputReader、InputDispatcher
InputManagerService和WMS交互,WMS记录所有窗口信息同步到IMS,IMS同步信息到Native,让InputDispatcher可以正确派发input事件到对应窗口。
InputReader从EventHub中取出input事件并封装,再把事件传递给InputDispatcher。
InputDispatcher接收InputReader传递过来的input事件,结合IMS传递过来的窗口信息,派发事件到合适的窗口。
Input系统相关的动态库:
libinputflinger.so:frameworks/native/services/inputflinger/
libinputservice.so:frameworks/base/libs/input/
libinput.so: frameworks/native/libs/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
- IInputConstants.aidl
frameworks/base/services/core/
- java/com/android/server/input/InputManagerService.java
- jni/com_android_server_input_InputManagerService.cpp
三:输入系统初始化
输入系统初始化的入口是InputManagerService(IMS),下面来从IMS的初始化流程解析Input系统的初始化流程
3.1 SystemServer.startOtherServices
IMS是系统服务,和AMS、WMS等一样,都是在SystemServer中进行初始化操作的
//frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...
InputManagerService inputManager = null;
...
try {
...
t.traceBegin("StartInputManagerService");
//初始化IMS
inputManager = new InputManagerService(context);
t.traceEnd();
...
//把IMS加入到ServiceManager中,这样其他地方就可以用过Context.INPUT_SERVICE获取到IMS这个系统服务
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
...
t.traceBegin("StartInputManager");
//把InputManagerCallback对象保存到IMS里
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
//启动IMS
inputManager.start();
t.traceEnd();
...
} catch (Throwable e) {...}
...
}
3.2 NativeInputManagerService.NativeImpl.init
IMS运行在"android.display"线程中,调用Native层的init函数来继续初始化流程
//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public InputManagerService(Context context) {
//IMS运行在"android.display"线程中
this(new Injector(context, DisplayThread.get().getLooper()));
}
//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
InputManagerService(Injector injector) {
...
//获取NativeInputManagerService对象
mNative = injector.getNativeService(this);
...
}
//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
static class Injector {
NativeInputManagerService getNativeService(InputManagerService service) {
//初始化NativeImpl
return new NativeInputManagerService.NativeImpl(service, mLooper.getQueue());
}
}
//frameworks/base/services/core/java/com/android/server/input/NativeInputManagerService.java
class NativeImpl implements NativeInputManagerService {
NativeImpl(InputManagerService service, MessageQueue messageQueue) {
mPtr = init(service, messageQueue);
}
private native long init(InputManagerService service, MessageQueue messageQueue);
}
3.3 com_android_server_input_InputManagerService.nativeInit
通过jni来初始化InputManager对象
//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject serviceObj,
jobject messageQueueObj) {
//获取native消息队列
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
...
std::call_once(nativeInitialize, [&]() {
//初始化NativeInputManager
im = new NativeInputManager(serviceObj, messageQueue->getLooper());
});
//返回native对象指针
return reinterpret_cast<jlong>(im);
}
//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject serviceObj, const sp<Looper>& looper)
: mLooper(looper), mInteractive(true) {
...
//初始化InputManager
InputManager* im = new InputManager(this, *this);
mInputManager = im;
defaultServiceManager()->addService(String16("inputflinger"), im);
}
3.4 InputManager.InputManager
在InputManager的构造函数中创建InputDispatcher和InputReader对象
//frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,
InputDispatcherPolicyInterface& dispatcherPolicy) {
//创建InputDispatcher
mDispatcher = createInputDispatcher(dispatcherPolicy);
...
//创建InputReader,这里的*mBlocker就是InputDispatcher
mReader = createInputReader(readerPolicy, *mBlocker);
}
3.5 InputDispatcher.InputDispatcher
在InputDispatcher构造函数中完成创建InputReporter对象、初始化DispatcherWindowListener对象,用于监听窗口焦点变化、添加DispatcherWindowListener监听器等工作
//frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
std::unique_ptr<InputDispatcherInterface> createInputDispatcher(
InputDispatcherPolicyInterface& policy) {
return std::make_unique<android::inputdispatcher::InputDispatcher>(policy);
}
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
std::chrono::nanoseconds staleEventTimeout)
: mPolicy(policy),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
mAppSwitchSawKeyDown(false),
mAppSwitchDueTime(LLONG_MAX),
mNextUnblockedEvent(nullptr),
//设置分发超时时间
mMonitorDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT),
mDispatchEnabled(false),
mDispatchFrozen(false),
mInputFilterEnabled(false),
mMaximumObscuringOpacityForTouch(1.0f),
mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
mWindowTokenWithPointerCapture(nullptr),
mStaleEventTimeout(staleEventTimeout),
mLatencyAggregator(),
mLatencyTracker(&mLatencyAggregator) {
...
mLooper = sp<Looper>::make(false);
//创建InputReporter对象
mReporter = createInputReporter();
//初始化DispatcherWindowListener对象,用于监听窗口焦点变化
mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
#if defined(__ANDROID__)
//添加DispatcherWindowListener监听器
SurfaceComposerClient::getDefault()->addWindowInfosListener(mWindowInfoListener);
#endif
...
}
3.6 InputReaderFactory.createInputReader
先创建EventHub对象然后作为参数创建InputReader对象
//frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
std::unique_ptr<InputReaderInterface> createInputReader(
const sp<InputReaderPolicyInterface>& policy, InputListenerInterface& listener) {
return std::make_unique<InputReader>(std::make_unique<EventHub>(), policy, listener);
}
3.7 EventHub.EventHub
EventHub在构造函数中主要完成了以下两个工作
- 初始化INotify(监听”/dev/input”),并添加到epoll实例
- 创建非阻塞模式的管道,并添加到epoll;
//frameworks/native/services/inputflinger/reader/EventHub.cpp
EventHub::EventHub(void)
: mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
mNextDeviceId(1),
mControllerNumbers(),
mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false),
mNeedToScanDevices(true),
mPendingEventCount(0),
mPendingEventIndex(0),
mPendingINotify(false) {
ensureProcessCanBlockSuspend();
//创建epoll
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
mINotifyFd = inotify_init1(IN_CLOEXEC);
std::error_code errorCode;
bool isDeviceInotifyAdded = false;
if (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {
//添加设备监听
addDeviceInputInotify();
} else {
...
}
...
//添加mINotifyFd到epoll实例
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
int wakeFds[2];
//创建管道
result = pipe2(wakeFds, O_CLOEXEC);
mWakeReadPipeFd = wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
//将pipe的读设置为非阻塞方式
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
//将pipe的写设置为非阻塞方式
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
eventItem.data.fd = mWakeReadPipeFd;
//添加管道的读端到epoll实例
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
}
//frameworks/native/services/inputflinger/reader/EventHub.cpp
void EventHub::addDeviceInputInotify() {
//监听"input/dev"路径下设备
mDeviceInputWd = inotify_add_watch(mINotifyFd, DEVICE_INPUT_PATH, IN_DELETE | IN_CREATE);
}
3.8 InputReader.InputReader
//frameworks/native/services/inputflinger/reader/InputReader.cpp
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
InputListenerInterface& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
//创建输入对象
mQueuedListener(listener),
mGlobalMetaState(AMETA_NONE),
mLedMetaState(AMETA_NONE),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
refreshConfigurationLocked(/*changes=*/{});
updateGlobalMetaStateLocked();
}
至此,Input系统的初始化流程完毕。
四:输入系统启动
Input系统完成初始化流程后,是如何启动的呢?回看3.1章节,在IMS初始化完成后,会调用IMS.start来进行启动流程。启动流程比较简单,主要做了以下两件事情
- 启动"InputDispatcher"线程,来接收InputReader传过来的input事件
- 启动"InputReader"线程,来循环读取input事件
//frameworks/base/services/core/java/com/android/server/input/NativeInputManagerService.java
class NativeImpl implements NativeInputManagerService {
@Override
public native void start();
//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jobject nativeImplObj) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
status_t result = im->getInputManager()->start();
...
}
//frameworks/native/services/inputflinger/InputManager.cpp
status_t InputManager::start() {
//启动InputDispatcher
status_t result = mDispatcher->start();
...
//启动InputReader
result = mReader->start();
...
}
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
status_t InputDispatcher::start() {
//启动"InputDispatcher"线程,来接收InputReader传过来的input事件
mThread = std::make_unique<InputThread>(
"InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
return OK;
}
//frameworks/native/services/inputflinger/reader/InputReader.cpp
status_t InputReader::start() {
//启动"InputReader"线程,来循环读取input事件
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
五:小结
从上述启动流程可以看出来,主要有三个线程和Input系统息息相关。IMS所在的"android.display"线程,InputDispatcher所在的"InputDispatcher"线程以及InputReader所在的"InputReader"线程。
"android.display"线程:属于Looper线程,用于处理Java层的IMS.InputManagerHandler和JNI层的NativeInputManager中指定的MessageHandler消息。
"InputDispatcher"线程:属于Looper线程,循环发送消息。
"InputReader"现成:通过EventHub的getEvents函数不断读取事件,然后进行封装、分发。
PS:"android.display"线程、"InputDispatcher"线程和"InputReader"线程均属于system_server进程。