虚拟机启动SystemServer后,SystemServer在StartOtherService中新建了InputManager对象。记下来看看InputManagerService中做了什么事情。
先看看InputManagerService的构造函数
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public InputManagerService(Context context) {
this.mContext = context;
//获得能和UI主进程交互的Handler
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
//调用了这个native层的初始化函数
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
这里看看这个nativeInit干了什么事情
private static native long nativeInit(InputManagerService service,Context context, MessageQueue messageQueue);
------JNI函数
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
{ "nativeInit","(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",(void*) nativeInit },
------JNI方法
static jlong nativeInit(JNIEnv* env, jclass clazz,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
//获得一个native MessageQueue对象
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
//new一个native InputManager对象,把刚才获得的native的message queue 对象传递给这个IM
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(im);
}
接下来看看这个native IM干了些什么事情。
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
//这个函数有个内置函数,直接返回一个InputManager的强指针
inline sp<InputManager> getInputManager() const { return mInputManager; }
//
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
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;
}
//新建了一个EventHub,然后根据这个EventHub新建了一个CPP层的InputManager对象,
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
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);
//创建一个epoll对象
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
//初始化一个INotifyFd对象,为应用监听文件系统提供帮助
mINotifyFd = inotify_init();
//将设备节点的路径dev/input/设置到INotifyFd对象中去
int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
//通过epoll_ctl,epoll事件注册函数,将INotifyFd对象注册到mEpollFd中去,这样当设备节点有读写变化的时候就会通过mINotifyFd向上进行通知。
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);
//管道文件描述符,描述一个管道的读端文件描述符和写端文件描述符.当一个线程的消息队列没有消息需要处理时,它就会在这个管道的读端文件描述符上进行睡眠等待.直到其他线程通过这个管道的写端文件描述符来唤醒它为止.
int wakeFds[2];
result = pipe(wakeFds);
mWakeReadPipeFd = wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
//设置管道文件描述符的新旗标
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
eventItem.data.u32 = EPOLL_ID_WAKE;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
int major, minor;
getLinuxRelease(&major, &minor);
mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);
}
epoll是一种I/O事件通知机制,是linux 内核同时监听多个输入输出源,在其中一个或多个输入输出源可用的时候返回,然后对其的进行读写操作的一个实现。
7368936-c868a5ee3b4cf9ff.png
NativeInputManager还新建了一个InputManager对象
/frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
//eventhub是NativeInputManager新建的,两个policy是NativeInputManager自身。
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
//这里新建了一个Dispatcher对象去分发事件,新建了一个Reader对象去读取事件
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
InputReader利用EventHub获取数据后,生成EventEntry事件,加入到InputDispatcher的mInboundQueue队列,再唤醒InputDispatcher线程。先看看initialize()函数干了什么事情,很简单的新建了mDispatcherThread和mReaderThread
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
然后前面讲到了systemserver在创建inputmanagerservice的时候就已经调用了start函数,这里的start就是run了新建的这两个读取分发线程。
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
if (result) {
return result;
}
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
if (result) {
mDispatcherThread->requestExit();
return result;
}
return OK;
}
InputReaderThread的ThreadLoop就是调用mReader的loopOnce。
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
mReader是一个InputReaderInterface内部接口对象,InputReaderInterface是处理input event数据并将处理好的数据发送给input的listerner,接口里面可以做一些input设备信息、状态信息的查询,判断物理按键是否匹配framework按键列表key值;最重要的方法就是上面的loopOnce,这个方法只能在InputReaderThread里面调用,用来处理读取和处理从eventhub过来的信息。
sp<InputReaderInterface> mReader;
//无穷无尽的从eventhub里面读取数据并处理
class InputReaderThread : public Thread {
public:
InputReaderThread(const sp<InputReaderInterface>& reader);
virtual ~InputReaderThread();
private:
sp<InputReaderInterface> mReader;
virtual bool threadLoop();
};
loopOnce查看InputReader配置是否修改,如界面大小、方向、键盘布局重新加载、指针速度改变等、从EventHub读取事件,其中EVENT_BUFFER_SIZE = 256、处理事件、将事件传到InputDispatcher,getEvent是阻塞式的,只有有事件或者被唤醒的时候才会执行。
20170609101625473.png
void InputReader::loopOnce() {
···
//从EventHub里面通过getEvent获取事件,
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
···
//如果count大于0就是代表有数据,就processEventsLocked处理
//原始输入事件、设备加载事件、设备卸载事件及FINISHED_DEVICE_SCAN事件
if (count) {
processEventsLocked(mEventBuffer, count);
}
···
//回调回java层通知input设备状态发生改变
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
···
//将数据送到listener,这里的listener就是diapatcher,为了防止死锁,flush操作放在了loopOnce的锁外面,因为dispatcher很有可能回调InputReader,如果也请求相同的锁对象就会死锁
mQueuedListener->flush();
}
processEventsLocked里会根据rawEvent的type进行事件的预处理,包含上面提到的四种操作,其中processEventsForDeviceLocked(deviceId, rawEvent, batchSize);会根据device id,先判断device会不会被忽略,然后不会被忽略就交给相应的设备进行处理,inputDevice会调用inputMapper进行处理
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
mapper->process(rawEvent);
}
···
//一共有这么多mapper
SwitchInputMapper
VibratorInputMapper
KeyboardInputMapper
CursorInputMapper
TouchInputMapper
SingleTouchInputMapper
MultiTouchInputMapper
JoystickInputMapper
···
5982616-ab16c91640ccbfa3.png
这里我们仅仅看看按键的mapper,调用getListener()->notifyKey(&args)调用的是QueuedInputListener的notifyKey函数,它里边有许多notifyXXX函数,做的事情都是将NotifyXXXArgs放入它的mArgsQueue队列中存储,等待处理。
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
int32_t scanCode = rawEvent->code;
int32_t usageCode = mCurrentHidUsage;
mCurrentHidUsage = 0;
if (isKeyboardOrGamepadKey(scanCode)) {
int32_t keyCode;
uint32_t flags;
if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
keyCode = AKEYCODE_UNKNOWN;
flags = 0;
}
processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
}
break;
}
case EV_MSC: {
if (rawEvent->code == MSC_SCAN) {
mCurrentHidUsage = rawEvent->value;
}
break;
}
case EV_SYN: {
if (rawEvent->code == SYN_REPORT) {
mCurrentHidUsage = 0;
}
}
}
}
processKey函数,当keydown,keyup的时候都会去找对应的keycode,scancode,还有down/up time,keyup的时候还要专门在map表里面清除key down的信息。
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
int32_t scanCode, uint32_t policyFlags) {
···
NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
getListener()->notifyKey(&args);
···
}
这里就通过getListener到InputDispacter里面notifyKey函数,mPolicy->interceptKeyBeforeQueueing(&event, /byref/ policyFlags);该函数最后会调用到java层的PhoneWindowManagerService函数,之后构造一个KeyEntry的对象,通过enqueueInboundEventLocked将按键事件入队列,入队成功,通过mLooper唤醒等待的InputDispatcher,进行事件分发。
KeyEvent event;
event.initialize(args->deviceId, args->source, args->action,
flags, keyCode, args->scanCode, metaState, 0,
args->downTime, args->eventTime);
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
bool needWake;
{ // acquire lock
mLock.lock();
if (shouldSendKeyToInputFilterLocked(args)) {
mLock.unlock();
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
return; // event was consumed by the filter
}
mLock.lock();
}
int32_t repeatCount = 0;
KeyEntry* newEntry = new KeyEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, flags, keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
if (needWake) {
mLooper->wake();
}
现在看看mQueuedListener.flush是个什么操作,把刚才args队列里面的事件全部通知给InputDispatcher,去到dispatcher里面继续执行。
···
sp<QueuedInputListener> mQueuedListener;
···
//InputListenerInterface 是input用来通知InputListener输入事件的接口
class InputListenerInterface : public virtual RefBase {
protected:
InputListenerInterface() { }
virtual ~InputListenerInterface() { }
public:
virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0;
virtual void notifyKey(const NotifyKeyArgs* args) = 0;
virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
};
···
//QueuedInputListener的构造函数就是新建一个这样的内部listener
QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
mInnerListener(innerListener) {
}
···
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
//NotifyArgs是所有input事件对象的父类
NotifyArgs* args = mArgsQueue[i];
args->notify(mInnerListener);
delete args;
}
mArgsQueue.clear();
}
图片.png
网友评论