android framework java层是如何拦截并分发底层传送来的按键事件
来源:互联网 发布:一览网络兼职是真的吗 编辑:程序博客网 时间:2024/05/19 21:59
android framework java层是如何拦截并分发底层传送来的按键事件
按键事件首先通过PhoneWindowManager的interceptKeyBeforeDispatching方法被拦截,然后分发到应用层,一些系统事件:HOME,MENU,SEARCH,会在这里做下预处理。那底层事件是如何传到interceptKeyBeforeDispatching方法中呢?
通过查看谁调用了此方法(eclipse中右键单击此方法名,选择open call hierarchy),发现InputMonitor.java调用了此方法:
- public long interceptKeyBeforeDispatching(
- InputWindowHandle focus, KeyEvent event, int policyFlags) {
- WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
- return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
- }
同样的方法我们发现InputManager.java中的Callbacks调用了InputMonitor的interceptKeyBeforeDispatching方法:
- @SuppressWarnings("unused")
- public long interceptKeyBeforeDispatching(InputWindowHandle focus,
- KeyEvent event, int policyFlags) {
- return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
- focus, event, policyFlags);
- }
java层就是通过InputManager.java和C++层完成事件交互,通过上述我们知道是Callbacks调用了interceptKeyBeforeDispatching方法,而Callbacks是什么呢,顾名思义,Callbacks是C++层回调InputManager.java的一个接口。那Callbacks是如何初始化和注册的呢?InputManager.java的构造方法给出了答案:
- public InputManager(Context context, WindowManagerService windowManagerService) {
- this.mContext = context;
- this.mWindowManagerService = windowManagerService;
- this.mCallbacks = new Callbacks();
- Looper looper = windowManagerService.mH.getLooper();
- Slog.i(TAG, "Initializing input manager");
- nativeInit(mContext, mCallbacks, looper.getQueue());
- // Add ourself to the Watchdog monitors.
- Watchdog.getInstance().addMonitor(this);
- }
nativeInit(mContext, mCallbacks, looper.getQueue());这是一个native方法,java层通过jni调用C++层相对应的方法。C++层相对应的方法会去初始化C++层的InputManager和注册Callbacks。
那么如何找到C++层这个相对应的方法呢?其实很简单,我们看下InputManager.java的路径
\frameworks\base\services\java\com\android\server\wm
通常在和java(\frameworks\base\services\java)同目录下会有相对应的jni的目录结构(\frameworks\base\services\jni)
通过Source Insight 搜索对应目录(PS这样快)下的nativeInit字串,发现这样的一个数组:
- static JNINativeMethod gInputManagerMethods[] = {
- /* name, signature, funcPtr */
- { "nativeInit", "(Landroid/content/Context;"
- "Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",
- (void*) android_server_InputManager_nativeInit },
android_server_InputManager_nativeInit就是C++层相对应的方法,在com_android_server_InputManager.cpp中:
- static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
- jobject contextObj, jobject callbacksObj, jobject messageQueueObj) {
- if (gNativeInputManager == NULL) {
- sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
- gNativeInputManager = new NativeInputManager(contextObj, callbacksObj, looper);
- } else {
- LOGE("Input manager already initialized.");
- jniThrowRuntimeException(env, "Input manager already initialized.");
- }
- }
- mInputManager = new InputManager(eventHub, this, this);
- 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();
- }
InputDispatcher中的doInterceptKeyBeforeDispatchingLockedInterruptible函数调用了mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
&event, entry->policyFlags);传入事件,mPolicy就是上面代码中的dispatcherPolicy对象。
- void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
- CommandEntry* commandEntry) {
- KeyEntry* entry = commandEntry->keyEntry;
- KeyEvent event;
- initializeKeyEvent(&event, entry);
- mLock.unlock();
- nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
- &event, entry->policyFlags);
- mLock.lock();
- if (delay < 0) {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
- } else if (!delay) {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
- } else {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
- entry->interceptKeyWakeupTime = now() + delay;
- }
- entry->release();
- }
InputDispatcher负责分发c++层获得的linux设备的按键事件,交由dispatcherPolicy,也就是NativeInputManager处理,NativeInputManager,通过Callbacks然后上报java层。
对于c++层如何获得的linux设备的按键事件,以及如何通过InputDispatcher分发这些事件感兴趣的,可以查看frameworks\base\services\input下的代码,可以先从InputManager.cpp的构造函数入手,或者查看网上相关文章。这里暂时不描述了。
- android framework java层是如何拦截并分发底层传送来的按键事件
- android framework java层是如何拦截并分发底层传送来的按键事件
- android framework java层是如何拦截并分发底层传送来的按键事件
- android framework java层是如何拦截并分发底层传送来的按键事件
- android framework java层是如何拦截并分发底层传送来的按键事件
- Android Framework Java层是如何拦截并分发底层传送来的按键事件
- Android Framework层如何截获按键消息
- Android按键分发流程之java层按键传递
- Android 事件拦截分发
- Android framework层 按键的处理流程
- Android Framework--事件分发
- Android事件分发,拦截的流程梳理
- Android触摸事件的分发、拦截、处理
- Android事件的分发、拦截和执行
- Android事件的分发、拦截和执行
- Android事件的分发与拦截机制
- android java层事件分发机制
- android中上层是如何接收按键事件的
- cocos2d-x节点(CCActionGrid.h)API
- 关于欧拉函数的东西 从性质开始
- Android--短信发送
- 日语动词变化总结
- Jsp和Servlet中引用路径问题
- android framework java层是如何拦截并分发底层传送来的按键事件
- 使用SSH登录内网机器
- c#关于委托和事件(一)(介绍的很详细)
- HDU1081二维子数组最大和/压缩/动态规划/DP
- 通过java后台拼接json字符串修改页面样式----一页多用 + 双引号(")和单引号(')截断字符串解决方案
- 【asp.net小札记】实现进度条
- Android的frameworks层键盘事件处理流程分析
- MVC 只是一个思想,不是模式!! (3)关于回显<特别重要>
- cocos2d-x节点(CCActionGrid3D.h)API