该篇文章接总章,来详细谈论说明InputManagerService 体系,从初始化到事件获取跟分发。咱们在进行前,先明确哪几个问题需要知道,然后看看在这篇文章中是否解决了这些问题。对于InputManagerService,大家第一个想知道是他起什么作用,这个在总章里面有详细说明,简而言之就是获得事件跟分发处理事件。那他如何或者跟其他模块配合获取事件?并且把这个事件进行分发?如何准确定位对应的处理事件的模块?咱们下面开始讨论这些问题,在这个文章出来的时候,android 已经到N了 ,也就是7.0。但是由于我的笔记(初稿) 在M的时候已经完成了,也就是去年。所以这篇文章还是基于M (6.0)来写。
InputManagerService的初始化:
跟其他模块一样,作为系统的核心服务初始化在SystemServer。基本系统的核心服务都是在这里初始化,这个可以研究下系统的启动流程,在启动的最后就是需要启动所有的核心服务。
代码路径: frameworks/base/services/java/com/android/server/SystemServer.java
在run 方法里面,M 是在startOtherService()里面初始化InputManagerService
上面主要是新建IMS(InputManagerService 下面都用这个替换) 对象, 然后把WindowManagerService的InputMonitor作为参数传给IMS,重点关注下InputMonitor,这个跟事件的分发有关。然后在这里调用start方法启动IMS,这里的start 实际是调用 native 的start 方法。
看下InputManagerServices的start方法:
代码路径:frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
上面主要调用了com_android_service_input_InputManagerService.cpp 里面的nativeStart方法,Java层的start方法主要做了两个工作:一个工作就是调用nativeStart方法。另外一个就是point 跟 toucher 相关参数设置跟监听,对应这Input事件的主要两类:Key 跟 toucher。在nativeStart里面的mPtr对应啥呢?首先Java层 跟 native层通信调用,主要通过JNI。这里主要是mPtr指针强制类型转换为NativeInputManager对象,看下源码:
Java层代码:
代码路径:frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
- // Pointer to native input manager service object.
- private final long mPtr;
- public InputManagerService(Context context) {
- this.mContext = context;
- this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
- <span style="white-space:pre;"> </span>mUseDevInputEventForAudioJack =
- context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
- Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
- + mUseDevInputEventForAudioJack);
- <span style="white-space:pre;"> </span>//这里对mPtr 进行初始化,调用的还是native的方法,把这个service跟 Systemcontext 传给native对应的方法
- mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
- <span style="white-space:pre;"> </span> LocalServices.addService(InputManagerInternal.class, new LocalService());
- }
// Pointer to native input manager service object.
private final long mPtr;
public InputManagerService(Context context) {
this.mContext = context;
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
//这里对mPtr 进行初始化,调用的还是native的方法,把这个service跟 Systemcontext 传给native对应的方法
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
Native层代码:
代码路径:/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;
- } //这里把JAVA层的 Systemcontext 以及IMS自己 作为参数传过来了
- an style="white-space:pre;"> </span>NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
- messageQueue->getLooper());
- im->incStrong(0);
- return reinterpret_cast<jlong>(im);
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;
} //这里把JAVA层的 Systemcontext 以及IMS自己 作为参数传过来了
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(im);
} 这个为什么要把IMS 传给NativeInputManager呢?看下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();
- 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;
- }
- <span style="white-space:pre;"> </span>mInteractive = true;
- <span style="white-space:pre;"> </span>//这个是从底层读取input 信息的提供者
- sp<EventHub> eventHub = new EventHub();
- mInputManager = new InputManager(eventHub, this, this);
- }
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;
}
mInteractive = true;
//这个是从底层读取input 信息的提供者
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
} 这里有一个重要的对象就是EventHub,如总章所说这个对象是事件获取的重要的对象。在这里也对Native层的InputManager进行了初始化。前面解决了mPtr 是啥,nativeStart又干了啥?
InputManagerService的读取跟分发启动:
- static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
- NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
- //这里就是上面获得InputManager对象调用start()方法返回的结果
- status_t result = im->getInputManager()->start();
- if (result) {
- jniThrowRuntimeException(env, "Input manager could not be started.");
- }
- }
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
//这里就是上面获得InputManager对象调用start()方法返回的结果
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
} 查看下InputManager的start方法到底干了什么?frameworks/native/services/inputFlinger/InputManager.cpp
代码路径:frameworks/native/services/inputFlinger/InputManager.cpp
- status_t InputManager::start() {
- status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
- if (result) {
- ALOGE("Could not start InputDispatcher thread due to error %d.", result);
- return result;
- }
- result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
- if (result) {
- ALOGE("Could not start InputReader thread due to error %d.", result);
- mDispatcherThread->requestExit();
- return result;
- }
- return OK;
- }
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
if (result) {
ALOGE("Could not start InputReader thread due to error %d.", result);
mDispatcherThread->requestExit();
return result;
}
return OK;
} 嘿嘿,这里就真正的Input 事件 消息读取分发的工作启动了,从上面的代码就可以知道这里开启了两个线程,这两个线程初始化在InputManager的initialize方法里面。
- void InputManager::initialize() {
- mReaderThread = new InputReaderThread(mReader);
- mDispatcherThread = new InputDispatcherThread(mDispatcher);
- }
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
} 这两个线程主要一个是读取事件,一个是分发事件。读取事件从哪里读呢?从EventHub里面读,源码说了~
代码路径:frameworks/native/services/inputflinger/InputReader.h
- /* Reads raw events from the event hub and processes them, endlessly. */ 这里说明了
- class InputReaderThread : public Thread {
- public:
- InputReaderThread(const sp<InputReaderInterface>& reader);
- virtual ~InputReaderThread();
- private:
- sp<InputReaderInterface> mReader;
- virtual bool threadLoop();
- };
/* Reads raw events from the event hub and processes them, endlessly. */ 这里说明了
class InputReaderThread : public Thread {
public:
InputReaderThread(const sp<InputReaderInterface>& reader);
virtual ~InputReaderThread();
private:
sp<InputReaderInterface> mReader;
virtual bool threadLoop();
}; 那这个线程如何读取数据呢?
代码路径:frameworks/native/services/inputflinger/InputReader.cpp
- // --- InputReaderThread ---
- InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
- Thread(/*canCallJava*/ true), mReader(reader) {
- }
- InputReaderThread::~InputReaderThread() {
- }
- bool InputReaderThread::threadLoop() {
// --- InputReaderThread ---
InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
Thread(/*canCallJava*/ true), mReader(reader) {
}
InputReaderThread::~InputReaderThread() {
}
bool InputReaderThread::threadLoop() {
- //调用loopOnce 方法
- mReader->loopOnce();
- return true;
//调用loopOnce 方法
mReader->loopOnce();
return true;
} InputReader 实际不直接访问设备点,而是通过EventHub 来完成这一工作,EventHub 通过读取/dev/input下的数据。loopOnce如何读取事件了,前面已经反复强调读取数据的工作主要是EventHub,那loopOnce里面EventHub就要一定要出现了。
- 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
- //获得input 数据
- size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
- //这里主要处理消息设备
- { // acquire lock
- AutoMutex _l(mLock);
- mReaderIsAliveCondition.broadcast();
- 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;
- getInputDevicesLocked(inputDevices);
- }
- } // release lock
- // Send out a message that the describes the changed input devices.
- if (inputDevicesChanged) {
- mPolicy->notifyInputDevicesChanged(inputDevices);
- }
- // Flush queued events out to the listener.
- // This must happen outside of the lock because the listener could potentially call
- // back into the InputReader's methods, such as getScanCodeState, or become blocked
- // on another thread similarly waiting to acquire the InputReader lock thereby
- // resulting in a deadlock. This situation is actually quite plausible because the
- // listener is actually the input dispatcher, which calls into the window manager,
- // which occasionally calls into the input reader.
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
//获得input 数据
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
//这里主要处理消息设备
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
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;
getInputDevicesLocked(inputDevices);
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
// Flush queued events out to the listener.
// This must happen outside of the lock because the listener could potentially call
// back into the InputReader's methods, such as getScanCodeState, or become blocked
// on another thread similarly waiting to acquire the InputReader lock thereby
// resulting in a deadlock. This situation is actually quite plausible because the
// listener is actually the input dispatcher, which calls into the window manager,
// which occasionally calls into the input reader.
- //获得数据后,刷新数据,mQueueListener,根据构造函数以及注释可以知道是InputDispatcher的一个封装
- //查看InputReader的构造函数, InputDispatcher 转成了这个
- //这里主要是刷新消息栈,进行事件的分发了
- //QueuedInputListener 定义在 InputListener.cpp里面
- mQueuedListener->flush();
- }
//获得数据后,刷新数据,mQueueListener,根据构造函数以及注释可以知道是InputDispatcher的一个封装
//查看InputReader的构造函数, InputDispatcher 转成了这个
//这里主要是刷新消息栈,进行事件的分发了
//QueuedInputListener 定义在 InputListener.cpp里面
mQueuedListener->flush();
} 看下loopOnce方法EventHub果然出现了,在这个几十行代码里面读取事件EventHub,flush 分发事件都有了,基本上就走完了Input事件的读取跟分发。现在准备进入事件分发的解读,事件的读取由于涉及到kernel层代码的解读,作为子章进行分析说明,本篇不做过多解读。这里从mQueuedListener->flush(); 开始说明。
代码路径:frameworks/native/services/inputflinger/InputListener.cpp
- 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 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();
} 代码路径:frameworks/native/services/inputflinger/inputListener.h
- /*
- * An implementation of the listener interface that queues up and defers dispatch
- * of decoded events until flushed.
- */
- class QueuedInputListener : public InputListenerInterface {
- protected:
- virtual ~QueuedInputListener();
- public:
- QueuedInputListener(const sp<InputListenerInterface>& innerListener);
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
- virtual void notifyKey(const NotifyKeyArgs* args);
- virtual void notifyMotion(const NotifyMotionArgs* args);
- virtual void notifySwitch(const NotifySwitchArgs* args);
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
- void flush();
- private:
- sp<InputListenerInterface> mInnerListener;
- Vector<NotifyArgs*> mArgsQueue;
- };
- /*
- * The interface used by the InputReader to notify the InputListener about input events.
- */
- 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;
- };
/*
* An implementation of the listener interface that queues up and defers dispatch
* of decoded events until flushed.
*/
class QueuedInputListener : public InputListenerInterface {
protected:
virtual ~QueuedInputListener();
public:
QueuedInputListener(const sp<InputListenerInterface>& innerListener);
virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
virtual void notifyKey(const NotifyKeyArgs* args);
virtual void notifyMotion(const NotifyMotionArgs* args);
virtual void notifySwitch(const NotifySwitchArgs* args);
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
void flush();
private:
sp<InputListenerInterface> mInnerListener;
Vector<NotifyArgs*> mArgsQueue;
};
/*
* The interface used by the InputReader to notify the InputListener about input events.
*/
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;
}; 由上可知继承inputListenerInterface的子类,会根据情况处理相应的事件。在这里有一个问题InputDispatcher 如何被强转的?其实是InputReader在初始化的时候InputDispatcher作为参数传了过去,然后强转了。上代码说明下:
- 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();
- }
- // --- InputReader ---
- InputReader::InputReader(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- //结合上面的代码 以及 这句代码可以知道inputdispatcher被强转了,为什么可以强转?
- //因为inputListenerInterface这个接口继承Refbase,Refbase是android里面的所有对象的父类
- //详情参考binder里面的介绍
- const sp<InputListenerInterface>& listener) :
- mContext(this), mEventHub(eventHub), mPolicy(policy),
- mGlobalMetaState(0), mGeneration(1),
- mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
- mConfigurationChangesToRefresh(0) {
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();
}
// --- InputReader ---
InputReader::InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
//结合上面的代码 以及 这句代码可以知道inputdispatcher被强转了,为什么可以强转?
//因为inputListenerInterface这个接口继承Refbase,Refbase是android里面的所有对象的父类
//详情参考binder里面的介绍
const sp<InputListenerInterface>& listener) :
mContext(this), mEventHub(eventHub), mPolicy(policy),
mGlobalMetaState(0), mGeneration(1),
mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) { 把InputDispatcher强转说清楚,咱们就开始详细了解下事情的分发过程,咱们从notifykey这方法说起
- 代码路径:frameworks/native/services/inputflinger/InputDispatcher.cpp
- void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
- Code 省略,前面主要检查这个事件有没有问题,把事件里面的信息属性都抽出来,重点看下面的代码
- 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
代码路径:frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
Code 省略,前面主要检查这个事件有没有问题,把事件里面的信息属性都抽出来,重点看下面的代码
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) {
if (needWake) {
- //事件分发主要在这里,但是要分发要看needWake的值,<span style="color:rgb(72,72,76);font-size:13px;line-height:1.38462;white-space:pre-wrap;background-color:rgb(247,247,249);">enqueueInboundEventLocked 返回true,事件就开始分发了</span>
- mLooper->wake();
- }
- }
//事件分发主要在这里,但是要分发要看needWake的值,enqueueInboundEventLocked 返回true,事件就开始分发了
mLooper->wake();
}
}
这里looper 什么怎么进行分发呢?还是看源码
- // --- InputDispatcherThread --- 这个主要在InputDispatcher.cpp里面
- InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
- Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
- }
- InputDispatcherThread::~InputDispatcherThread() {
- }
- . bool InputDispatcherThread::threadLoop() {
- //开始调用dispatchOnce方法
- mDispatcher->dispatchOnce();
- return true;
- . }
- . } // namespace android
// --- InputDispatcherThread --- 这个主要在InputDispatcher.cpp里面
InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
}
InputDispatcherThread::~InputDispatcherThread() {
}
. bool InputDispatcherThread::threadLoop() {
//开始调用dispatchOnce方法
mDispatcher->dispatchOnce();
return true;
. }
. } // namespace android
- void InputDispatcher::dispatchOnce() {
- nsecs_t nextWakeupTime = LONG_LONG_MAX;
- { // acquire lock
- AutoMutex _l(mLock);
- mDispatcherIsAliveCondition.broadcast();
- // Run a dispatch loop if there are no pending commands.
- // The dispatch loop might enqueue commands to run afterwards.
- if (!haveCommandsLocked()) {
- //调用下面的方法
- dispatchOnceInnerLocked(&nextWakeupTime);
- }
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
// Run a dispatch loop if there are no pending commands.
// The dispatch loop might enqueue commands to run afterwards.
if (!haveCommandsLocked()) {
//调用下面的方法
dispatchOnceInnerLocked(&nextWakeupTime);
} 到这里就开始说明分发事件了,TouchEvent的消息分发结构来分析Input 在Framework的使用
- Code In InputDispatcher.cpp 里面
- void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
- Code 省略
- 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;
- }
- //跳转到下面个函数,去处理motion相关操作
- done = dispatchMotionLocked(currentTime, typedEntry,
- &dropReason, nextWakeupTime);
- break;
- }
Code In InputDispatcher.cpp 里面
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
Code 省略
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;
}
//跳转到下面个函数,去处理motion相关操作
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
}
- bool InputDispatcher::dispatchMotionLocked(
- nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
- //进行motion事件,进行处理
- // Preprocessing.
- if (! entry->dispatchInProgress) {
- entry->dispatchInProgress = true;
- //这个函数把motion的相关值打出来
- logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
- }
- // Clean up if dropping the event.
- 把旧有的数据清楚掉
- if (*dropReason != DROP_REASON_NOT_DROPPED) {
- //这个方法就是设置插入结果,根据不同InjectionRest弹出不同LOG
- setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
- ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
- return true;
- }
- //判断时间的类型
- bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
- //获得事件的接受者或者实际响应者
- // Identify targets.
- Vector<InputTarget> inputTargets;
- bool conflictingPointerActions = false;
- int32_t injectionResult;
- if (isPointerEvent) {
- // Pointer event. (eg. touchscreen)
- // 获得对应的window 是 touch 事件,这里是重点
- injectionResult = findTouchedWindowTargetsLocked(currentTime,
- entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
- } else {
- // Non touch event. (eg. trackball)
- // 是轨迹事件
- injectionResult = findFocusedWindowTargetsLocked(currentTime,
- entry, inputTargets, nextWakeupTime);
- }
- // 是否延迟处理
- if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
- return false;
- }
- // 设置延迟处理
- setInjectionResultLocked(entry, injectionResult);
- if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
- if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
- CancelationOptions::Mode mode(isPointerEvent ?
- CancelationOptions::CANCEL_POINTER_EVENTS :
- CancelationOptions::CANCEL_NON_POINTER_EVENTS);
- CancelationOptions options(mode, "input event injection failed");
- synthesizeCancelationEventsForMonitorsLocked(options);
- }
- return true;
- }
- //支持 发送二次输入显示器的显示事件
- // TODO: support sending secondary display events to input monitors
- if (isMainDisplay(entry->displayId)) {
- addMonitoringTargetsLocked(inputTargets);
- }
- // Dispatch the motion.
- if (conflictingPointerActions) {
- CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "conflicting pointer actions");
- synthesizeCancelationEventsForAllConnectionsLocked(options);
- }
- dispatchEventLocked(currentTime, entry, inputTargets);
- return true;
- }
bool InputDispatcher::dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
//进行motion事件,进行处理
// Preprocessing.
if (! entry->dispatchInProgress) {
entry->dispatchInProgress = true;
//这个函数把motion的相关值打出来
logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
}
// Clean up if dropping the event.
把旧有的数据清楚掉
if (*dropReason != DROP_REASON_NOT_DROPPED) {
//这个方法就是设置插入结果,根据不同InjectionRest弹出不同LOG
setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
return true;
}
//判断时间的类型
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
//获得事件的接受者或者实际响应者
// Identify targets.
Vector<InputTarget> inputTargets;
bool conflictingPointerActions = false;
int32_t injectionResult;
if (isPointerEvent) {
// Pointer event. (eg. touchscreen)
// 获得对应的window 是 touch 事件,这里是重点
injectionResult = findTouchedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
} else {
// Non touch event. (eg. trackball)
// 是轨迹事件
injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
}
// 是否延迟处理
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
// 设置延迟处理
setInjectionResultLocked(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
CancelationOptions::Mode mode(isPointerEvent ?
CancelationOptions::CANCEL_POINTER_EVENTS :
CancelationOptions::CANCEL_NON_POINTER_EVENTS);
CancelationOptions options(mode, "input event injection failed");
synthesizeCancelationEventsForMonitorsLocked(options);
}
return true;
}
//支持 发送二次输入显示器的显示事件
// TODO: support sending secondary display events to input monitors
if (isMainDisplay(entry->displayId)) {
addMonitoringTargetsLocked(inputTargets);
}
// Dispatch the motion.
if (conflictingPointerActions) {
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
"conflicting pointer actions");
synthesizeCancelationEventsForAllConnectionsLocked(options);
}
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
} 这里大概就是touch事件的处理流程, findTouchedWindowTargetsLocked 是找到对应的事件响应者的重要方法,下面开始详细说明
- Code In InputDispatcher
- int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
- const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
- int32_t injectionResult;
- String8 reason;
Code In InputDispatcher
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
int32_t injectionResult;
String8 reason;
//这里判断是否有焦点的窗口跟焦点的应用
// If there is no currently focused window and no focused application // then drop the event. 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;
- }
- // Check permissions. 检查权限
- if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
- injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- goto Failed;
- }
// Check permissions. 检查权限
if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
goto Failed;
}
- // Check whether the window is ready for more input.
// Check whether the window is ready for more input.
- // 检查窗口的状态,比如是否pause 等等
- reason = checkWindowReadyForMoreInputLocked(currentTime,
- mFocusedWindowHandle, entry, "focused");
- if (!reason.isEmpty()) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.string());
- goto Unresponsive;
- }
// 检查窗口的状态,比如是否pause 等等
reason = checkWindowReadyForMoreInputLocked(currentTime,
mFocusedWindowHandle, entry, "focused");
if (!reason.isEmpty()) {
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.string());
goto Unresponsive;
}
- // Success! Output targets.
// Success! Output targets.
- // 这里主要是Input 跟 目标窗口相关信息复制跟绑定,重点关注里面的InputChannel,这个跟窗口年消息通信有关
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
- addWindowTargetLocked(mFocusedWindowHandle,
- InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
- inputTargets);
// 这里主要是Input 跟 目标窗口相关信息复制跟绑定,重点关注里面的InputChannel,这个跟窗口年消息通信有关
injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
addWindowTargetLocked(mFocusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
inputTargets);
- // Done.
- Failed:
- Unresponsive:
- nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatisticsLocked(currentTime, entry,
- injectionResult, timeSpentWaitingForApplication);
- #if DEBUG_FOCUS
// Done.
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;
ALOGD("findFocusedWindow finished: injectionResult=%d, "
"timeSpentWaitingForApplication=%0.1fms",
injectionResult, timeSpentWaitingForApplication / 1000000.0);
#endif
return injectionResult;
上面重点要关注的就是mFocusedWindowHandle 跟
mFocusedApplicationHandle 。他们是谁复制的呢?如何复制的呢?起什么作用了。明白了他们两个就可以明白了Input 跟对应的window的通信。下面就主要从这两个对象进行研究展开。findFocusedWindowTargetsLocked 的方法里面其他就是检查窗口状态等相关信息。
mFocusedWindowHandler 谁复制的呢?经过查询在InputDispatcher 里面就如下的方法
- void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
- Code 省略
- // newFocusedWindowHandler
- sp<InputWindowHandle> newFocusedWindowHandle;
- //mFocusedWindowHandler 是被赋值为newFocusedWindowHandle
- mFocusedWindowHandle = newFocusedWindowHandle;
- Code 省略
void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
Code 省略
// newFocusedWindowHandler
sp<InputWindowHandle> newFocusedWindowHandle;
//mFocusedWindowHandler 是被赋值为newFocusedWindowHandle
mFocusedWindowHandle = newFocusedWindowHandle;
Code 省略 这里就是InputDispatcher 设置对应的消息输出窗口的地方,但是到底这个方法到底谁在用?什么地方用?由于咱们讨论的是IMS 整个体系,InputDispatcher跟InputReader 是IMS 的左膀右臂。InputReader是负责的读取的数据然后应该是给IMS 去处理,InputDispatcher 是分发的,应该也是由IMS 去具体处理。咱们去IMS看看是否有设置窗口的调用
看下InputManagerService.java
代码路径:frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public void setInputWindows(InputWindowHandle[] windowHandles) {
- //这里调用com_android_server_input_InputManagerService.cpp
- nativeSetInputWindows(mPtr, windowHandles);
- }
//这里调用com_android_server_input_InputManagerService.cpp
nativeSetInputWindows(mPtr, windowHandles);
} 代码路径:frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
- 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
- }
- sp<InputWindowHandle> windowHandle =
- android_server_InputWindowHandle_getHandle(env, windowHandleObj);
- if (windowHandle != NULL) {
- windowHandles.push(windowHandle);
- }
- env->DeleteLocalRef(windowHandleObj);
- }
- }
- //这里会调用InputManager.cpp里面的方法
- mInputManager->getDispatcher()->setInputWindows(windowHandles);
- CODE 省略
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
}
sp<InputWindowHandle> windowHandle =
android_server_InputWindowHandle_getHandle(env, windowHandleObj);
if (windowHandle != NULL) {
windowHandles.push(windowHandle);
}
env->DeleteLocalRef(windowHandleObj);
}
}
//这里会调用InputManager.cpp里面的方法
mInputManager->getDispatcher()->setInputWindows(windowHandles);
CODE 省略 代码路径:frameworks/native/services/inputflinger/inputManager.cpp
- sp<InputDispatcherInterface> InputManager::getDispatcher() {
- //获得InputDispatcheer.cpp 对象
- return mDispatcher;
sp<InputDispatcherInterface> InputManager::getDispatcher() {
//获得InputDispatcheer.cpp 对象
return mDispatcher; 从上面可以知道IMS 到 InputDispather 如何层层调用setInputWindow的流程,但是这个方法还是在IMS 体系里面调用,外面别人如何调用呢?既然从IMS 体系找不到,就从外面找,window 的管理者WMS。
代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
看下WMS 的 addWindow方法
- Code In WindowManagerService.java
- public int addWindow(Session session, IWindow client, int seq,
- WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
- Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
- InputChannel outInputChannel) {
- Code 省略
- if (focusChanged) {
- //调用InputMonitor的方法设置接收窗口
- mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
- }
- mInputMonitor.updateInputWindowsLw(false /*force*/);
- Code 省略
Code In WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
Code 省略
if (focusChanged) {
//调用InputMonitor的方法设置接收窗口
mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
}
mInputMonitor.updateInputWindowsLw(false /*force*/);
Code 省略 来看下InputMonitor 在干啥
代码路径:frameworks/base/services/core/java/com/android/server/wm/inputMonitor.java
- /* Called when the current input focus changes.
- * Layer assignment is assumed to be complete by the time this is called.
- */
- public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
- if (WindowManagerService.DEBUG_FOCUS_LIGHT || WindowManagerService.DEBUG_INPUT) {
- Slog.d(WindowManagerService.TAG, "Input focus has changed to " + newWindow);
- }
- if (newWindow != mInputFocus) {
- if (newWindow != null && newWindow.canReceiveKeys()) {
- // Displaying a window implicitly causes dispatching to be unpaused.
- // This is to protect against bugs if someone pauses dispatching but
- // forgets to resume.
- newWindow.mToken.paused = false;
- }
- mInputFocus = newWindow;
- setUpdateInputWindowsNeededLw();
- if (updateInputWindows) {
- //更新当前焦点窗口
- updateInputWindowsLw(false /*force*/);
- }
- }
- }
/* Called when the current input focus changes.
* Layer assignment is assumed to be complete by the time this is called.
*/
public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
if (WindowManagerService.DEBUG_FOCUS_LIGHT || WindowManagerService.DEBUG_INPUT) {
Slog.d(WindowManagerService.TAG, "Input focus has changed to " + newWindow);
}
if (newWindow != mInputFocus) {
if (newWindow != null && newWindow.canReceiveKeys()) {
// Displaying a window implicitly causes dispatching to be unpaused.
// This is to protect against bugs if someone pauses dispatching but
// forgets to resume.
newWindow.mToken.paused = false;
}
mInputFocus = newWindow;
setUpdateInputWindowsNeededLw();
if (updateInputWindows) {
//更新当前焦点窗口
updateInputWindowsLw(false /*force*/);
}
}
}
- /* Updates the cached window information provided to the input dispatcher. */
- public void updateInputWindowsLw(boolean force) {
- if (!force && !mUpdateInputWindowsNeeded) {
- return;
- }
- Code 省略
- //在这个方法里面会调用InputManagerService的setInputWindow方法传入
- //inputWindowHandlers
- // Send windows to native code.
- mService.mInputManager.setInputWindows(mInputWindowHandles);
- // Clear the list in preparation for the next round.
- clearInputWindowHandlesLw();
- if (false) Slog.d(WindowManagerService.TAG, "<<<<<<< EXITED updateInputWindowsLw");
- }
/* Updates the cached window information provided to the input dispatcher. */
public void updateInputWindowsLw(boolean force) {
if (!force && !mUpdateInputWindowsNeeded) {
return;
}
Code 省略
//在这个方法里面会调用InputManagerService的setInputWindow方法传入
//inputWindowHandlers
// Send windows to native code.
mService.mInputManager.setInputWindows(mInputWindowHandles);
// Clear the list in preparation for the next round.
clearInputWindowHandlesLw();
if (false) Slog.d(WindowManagerService.TAG, "<<<<<<< EXITED updateInputWindowsLw");
} 到这里就实现了WMS 通过InputMonitor 跟IMS 再 InputDispather的沟通,也就是Window 跟 Input事件的沟通了。说完他们之间的关系,就说最后一部分他们的通信渠道了。先说结论对应的window 跟 IMS 通信实际是用InputChannel。InputChannel是一个pipe,底层实际是通过socket进行通信。
看下inputChannel的源码:
代码路径:frameworks\base\core\java\android\view\InputChannel.java
- Creates a new input channel pair. One channel should be provided to the input
- * dispatcher and the other to the application's input queue.
- * @param name The descriptive (non-unique) name of the channel pair.
- * @return A pair of input channels. The first channel is designated as the
- * server channel and should be used to publish input events. The second channel
- * is designated as the client channel and should be used to consume input events.
- 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 + "'");
- }
Creates a new input channel pair. One channel should be provided to the input
* dispatcher and the other to the application's input queue.
* @param name The descriptive (non-unique) name of the channel pair.
* @return A pair of input channels. The first channel is designated as the
* server channel and should be used to publish input events. The second channel
* is designated as the client channel and should be used to consume input events.
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);
- }
//这里还要走底层的代码
return nativeOpenInputChannelPair(name);
} 代码路径: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);
- //这里主要是建立了一堆通信的inputchannel
- sp<InputChannel> serverChannel;
- sp<InputChannel> clientChannel;
- status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
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);
//这里主要是建立了一堆通信的inputchannel
sp<InputChannel> serverChannel;
sp<InputChannel> clientChannel;
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
- 代码省略
代码省略 上面代码说明了为了通信,建立了一对inputChannel,那如何跟socket关联了?看下面的代码
代码路径:frameworks\native\libs\input\InputTransport.cpp
- 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;
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的open方法其实就是建立了socket通信
IMS体系建立了inputChannel,那WMS也相应的做了InputChannel的相关操作
代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
- public int addWindow(Session session, IWindow client, int seq,
- WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
- Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
- InputChannel outInputChannel) {
- int[] appOp = new int[1];
- int res = mPolicy.checkAddPermission(attrs, appOp);
- if (res != WindowManagerGlobal.ADD_OKAY) {
- CODE 省略
- if (outInputChannel != null && (attrs.inputFeatures
- & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
- /** M: [ALPS00044207] @{ */
- try {
- //设置当前通道的名字
- String name = win.makeInputChannelName();
- //打开一对通道
- InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
- win.setInputChannel(inputChannels[0]);
- inputChannels[1].transferTo(outInputChannel);
- mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
- } catch (IllegalArgumentException e) {
- Slog.w(TAG, "handle Input channel erorr", e);
- return WindowManagerGlobal.ADD_INPUTCHANNEL_NOT_ALLOWED;
- }
- /** @} */
- }
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
int[] appOp = new int[1];
int res = mPolicy.checkAddPermission(attrs, appOp);
if (res != WindowManagerGlobal.ADD_OKAY) {
CODE 省略
if (outInputChannel != null && (attrs.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
/** M: [ALPS00044207] @{ */
try {
//设置当前通道的名字
String name = win.makeInputChannelName();
//打开一对通道
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
win.setInputChannel(inputChannels[0]);
inputChannels[1].transferTo(outInputChannel);
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
} catch (IllegalArgumentException e) {
Slog.w(TAG, "handle Input channel erorr", e);
return WindowManagerGlobal.ADD_INPUTCHANNEL_NOT_ALLOWED;
}
/** @} */
}
到了这里基本IMS 关于消息的处理至少在framework层讲得差不多了。做个总结吧,也把开头的问题回答下,其实文中已经说得很清楚了。
InputManager初始化跟其他的核心service一样都是在systemServer里面进行(这里估计有问题),初始化后,会调用start方法。其实调用的是native层inputmanager的start方法,这里初始化了两个线程。native层的inputmanager的构造函数里面会对InputReader/ InputDispatcher进行初始化,Eventhub(读取dev/input里面的事件)和InputDispatcher作为参数传给了InputReader
Work
一:消息处理,inputReader通过EventHub获得数据后,会通知QueuedInputListener调用flush方法,由上面的详细笔记可以知道QueuedInputListener继承InputListenerInterface,InputListenerInterface 是继承Refbase,InputDispatcher作为参数传给了QueuedInputListener。
二:QueuedInputListener.flush方法会调用子类的notify方法,至于notify是key,还是其他,具体情况具体处理。
Inputdispatcher跟WMS的交互,主要在findfocuswindow函数里面实现,关键在setWindow方法传递windowHandler。
setWindow方法都是通过成员变量调方法,进行windowHandler传递。WMS里面有inputmonitor作为成员变量在里面,在InputMonitor里面会调用native InputManagerService的setInputWindow方法,在这个方法里面会通过InputManager调用inputDispatcher方法里面的setInputWindow方法,完成windowHandler的传递。
三:可以知道windowHandler上面有inputChannel,inputChannel是android里面的pipe 管道通信。实现了应用程序跟InputDispatcher的通信
注:mQueuedListener->flush();如何跟InputDispatcher联系上?
在InputRead.cpp的构造函数里面,inputDispatcher作为参数传给了QueuedInputListener里。
QueuedInputListener定义在InputListener.h 里面,InputDispatcher作为参数,到了QueuedInputListener的构造函数里,传给mInnerListener()这个方法里面
问题:那他如何或者跟其他模块配合获取事件?并且把这个事件进行分发?如何准确定位对应的处理事件的模块?
1.其实通过调用,里面有对应的对象调用相对的方法,进行配合使用。
2.分发其实找到对应的window ,然后会建立对应的一对inputchannel进行通信。
Ok,写完了,其实去年就写完了,一直没时间整理发博客。今天大概全部整理了下发出来了。希望能跟各位多多交流。吐槽一句优快云的博客真不好编辑代码的。
本文深入探讨了Android系统中InputManagerService的初始化过程及其事件获取与分发机制。重点介绍了InputManagerService如何与其他模块协作,实现事件的有效处理,并详细解释了inputChannel在这一过程中的作用。
4145

被折叠的 条评论
为什么被折叠?



