从这一节里面,我们开始介绍InputManagerService部分的知识。它用于管理整个系统的输入部分,包括键盘、鼠标、触摸屏等等。这一章里面我们主要就要介绍IMS。首先从IMS的启动来分析:
- public InputManagerService(Context context, Handler handler) {
- this.mContext = context;
- this.mHandler = new InputManagerHandler(handler.getLooper());
-
- mUseDevInputEventForAudioJack =
- context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
- mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
- }
这里首先构造InputManagerHandler用于处理消息,当然这个handle是绑定在"WindowManager"这个looper上的。然后调用nativeInit去完成初natvie层的初始化:
- static jint nativeInit(JNIEnv* env, jclass clazz,
- jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
- sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
-
- NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
- messageQueue->getLooper());
- im->incStrong(0);
- return reinterpret_cast<jint>(im);
- }
android_os_MessageQueue_getMessageQueue这个函数我们在介绍Looper的时候已经分析过,因为Java层的MessageQueue总是对应native层的NativeMessageQueue对象,所以首先先取得native层的messageQueue,并构造NativeInputManager对象:
- NativeInputManager::NativeInputManager(jobject contextObj,
- jobject serviceObj, const sp<Looper>& looper) :
- mLooper(looper) {
- JNIEnv* env = jniEnv();
-
- 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;
- }
-
- sp<EventHub> eventHub = new EventHub();
- mInputManager = new InputManager(eventHub, this, this);
- }
上面的InputManagerService的NativeInputManager的类图关系如下:
在NativeInputManager的构造函数中,首先对mLocked中的一些变量赋初值。然后构造EventHub对象,并通过它最终构造InputManager对象。首先来看EventHub的构造函数:
- 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);
-
- mEpollFd = epoll_create(EPOLL_SIZE_HINT);
- LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
-
- mINotifyFd = inotify_init();
- 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);
-
- struct epoll_event eventItem;
- memset(&eventItem, 0, sizeof(eventItem));
- eventItem.events = EPOLLIN;
- eventItem.data.u32 = EPOLL_ID_INOTIFY;
- 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;
- 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);
- }
首先是对一些成员变量做初始化,这些变量等到我们用到时再来一一介绍。然后调用inotify机制对/dev/input文件目录下的增和删操作做监听,/dev/input目录就是所有的input设备文件。并调用epoll机制EPOLL_CTL_ADD命令对上面的inotify的句柄和mWakeReadPipeFd句柄加入到epoll的句柄mEpollFd中。我们可以看到当有/dev/input下面的增删操作或者在mWakeWritePipeFd中写数据时,epoll_wait将会返回。再来看InputManager的构造函数:
- InputManager::InputManager(
- const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& readerPolicy,
- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
- mDispatcher = new InputDispatcher(dispatcherPolicy);
- mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
- initialize();
- }
-
- void InputManager::initialize() {
- mReaderThread = new InputReaderThread(mReader);
- mDispatcherThread = new InputDispatcherThread(mDispatcher);
- }
这InputManager的构造函数中首先构造InputDispatcher和InputReader两个对象,然后在initialize构造InputReaderThread和InputDispatcherThread分别用于收按键输入和分发按键消息。InputDispatcher是分发消息的对象,InputReader是从驱动获取按键消息,首先来看一下它们的构造函数:
- InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
- mPolicy(policy),
- mPendingEvent(NULL), 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);
- }
InputDispatcher的构造函数中首先初始化一些成员变量,然后构造一个Native层的Looper,并通过IMS获取VirtualKeyQuietime和ExcludedDevice系统配置保存到InputDispatcherConfiguration选项。接着来看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);
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- refreshConfigurationLocked(0);
- updateGlobalMetaStateLocked();
- } // release lock
- }
这里首先由传入的InputDispatcher构造一个QueuedInputListener并保存在mQueuedListener中。回到InputManager的构造函数中,接着调用initialize构造分别构造InputReaderThread和InputDispatcherThread两个thread。
InputReader和InputDispatcher两个类都比较庞大,我们先来看一下它们的类图:
再来看一下上面IMS构造过程的流程图:
到这里InputManagerService的构造函数就介绍完了,回到SystemService中接着调用WMS的main方法,并把前面创建的InputManagerService作为参数传入:
- private WindowManagerService(Context context, PowerManagerService pm,
- DisplayManagerService displayManager, InputManagerService inputManager,
- boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
-
- ......
-
- mInputManager = inputManager; // Must be before createDisplayContentLocked.
-
- mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
-
- .....
- }
在WMS的构造函数中,首先在mInputManager中保存InputManagerService对象,然后构造PointerEventDispatcher对用于分析点击事件。首先来看InputManagerService的monitorInput方法:
- public InputChannel monitorInput(String inputChannelName) {
- InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
- nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
- inputChannels[0].dispose(); // don't need to retain the Java object reference
- return inputChannels[1];
- }
先来看一下InputChannel的类图结构:
InputChannel用于从InputDispatcher中后去所有的input消息,所以这里构造一对InputChannel,一个注册到底层的InputDispatcher中,一个用于PointerEventDispatcher给activity分发消息。先来看InputChannel的openInputChannelPair函数:
- public static InputChannel[] openInputChannelPair(String name) {
- return nativeOpenInputChannelPair(name);
- }
-
- 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;
- }
android_view_InputChannel_nativeOpenInputChannelPair函数首先调用Native层的InputChannel的openInputChannelPair函数创建一对socket,先来看openInputChannelPair的实现:
- 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;
- }
上面的代码比较简单,首先创建一对未命名、相互连接的UNIX域套接字,然后分别通过Fd分别构造两个Native层的InputChannel代表server和client端。在android_view_InputChannel_nativeOpenInputChannelPair函数中把Native层的InputChannel和Java层的InputChannel通过NativeInputChannel相互绑定起来。
回到InputManagerService的monitorInput方法中,InputChannel的openInputChannelPair返回一对InputChannel对象,其中index为0的代表server端,index为1的代表client端。接着调用nativeRegisterInputChannel把InputChannel[0]到InputDispatcher,用于从InputDispatcher获取触摸事件: