android framework java层是如何拦截并分发底层传送来的按键事件

转载 2013年12月02日 19:10:55

本文转自:http://blog.csdn.net/cool_ping/article/details/8363212


按键事件首先通过PhoneWindowManager的interceptKeyBeforeDispatching方法被拦截,然后分发到应用层,一些系统事件:HOME,MENU,SEARCH,会在这里做下预处理。那底层事件是如何传到interceptKeyBeforeDispatching方法中呢?

通过查看谁调用了此方法(eclipse中右键单击此方法名,选择open call hierarchy),发现InputMonitor.java调用了此方法:

[java] view plaincopy
  1. public long interceptKeyBeforeDispatching(  
  2.             InputWindowHandle focus, KeyEvent event, int policyFlags) {  
  3.         WindowState windowState = focus != null ? (WindowState) focus.windowState : null;  
  4.         return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);  
  5.     }  

同样的方法我们发现InputManager.java中的Callbacks调用了InputMonitor的interceptKeyBeforeDispatching方法:

[java] view plaincopy
  1. @SuppressWarnings("unused")  
  2.         public long interceptKeyBeforeDispatching(InputWindowHandle focus,  
  3.                 KeyEvent event, int policyFlags) {  
  4.             return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(  
  5.                     focus, event, policyFlags);  
  6.         }  

java层就是通过InputManager.java和C++层完成事件交互,通过上述我们知道是Callbacks调用了interceptKeyBeforeDispatching方法,而Callbacks是什么呢,顾名思义,Callbacks是C++层回调InputManager.java的一个接口。那Callbacks是如何初始化和注册的呢?InputManager.java的构造方法给出了答案:

[java] view plaincopy
  1. public InputManager(Context context, WindowManagerService windowManagerService) {  
  2.         this.mContext = context;  
  3.         this.mWindowManagerService = windowManagerService;  
  4.         this.mCallbacks = new Callbacks();  
  5.   
  6.         Looper looper = windowManagerService.mH.getLooper();  
  7.   
  8.         Slog.i(TAG, "Initializing input manager");  
  9.         nativeInit(mContext, mCallbacks, looper.getQueue());  
  10.   
  11.         // Add ourself to the Watchdog monitors.  
  12.         Watchdog.getInstance().addMonitor(this);  
  13.     }  

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字串,发现这样的一个数组:

  1. static JNINativeMethod gInputManagerMethods[] = {  
  2.     /* name, signature, funcPtr */  
  3.     { "nativeInit""(Landroid/content/Context;"  
  4.             "Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",  
  5.             (void*) android_server_InputManager_nativeInit },  


android_server_InputManager_nativeInit就是C++层相对应的方法,在com_android_server_InputManager.cpp中:

  1. static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,  
  2.         jobject contextObj, jobject callbacksObj, jobject messageQueueObj) {  
  3.     if (gNativeInputManager == NULL) {  
  4.         sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);  
  5.         gNativeInputManager = new NativeInputManager(contextObj, callbacksObj, looper);  
  6.     } else {  
  7.         LOGE("Input manager already initialized.");  
  8.         jniThrowRuntimeException(env, "Input manager already initialized.");  
  9.     }  
  10. }  


NativeInputManager的构造函数中:

  1. mInputManager = new InputManager(eventHub, thisthis);  


InputManager.cpp 存在于frameworks\base\services\input,构造函数中:

  1. InputManager::InputManager(  
  2.         const sp<EventHubInterface>& eventHub,  
  3.         const sp<InputReaderPolicyInterface>& readerPolicy,  
  4.         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {  
  5.     mDispatcher = new InputDispatcher(dispatcherPolicy);  
  6.     mReader = new InputReader(eventHub, readerPolicy, mDispatcher);  
  7.     initialize();  
  8. }  


InputDispatcher中的doInterceptKeyBeforeDispatchingLockedInterruptible函数调用了mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
            &event, entry->policyFlags);传入事件,mPolicy就是上面代码中的dispatcherPolicy对象。

  1. void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(  
  2.         CommandEntry* commandEntry) {  
  3.     KeyEntry* entry = commandEntry->keyEntry;  
  4.   
  5.     KeyEvent event;  
  6.     initializeKeyEvent(&event, entry);  
  7.   
  8.     mLock.unlock();  
  9.   
  10.     nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,  
  11.             &event, entry->policyFlags);  
  12.   
  13.     mLock.lock();  
  14.   
  15.     if (delay < 0) {  
  16.         entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;  
  17.     } else if (!delay) {  
  18.         entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;  
  19.     } else {  
  20.         entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;  
  21.         entry->interceptKeyWakeupTime = now() + delay;  
  22.     }  
  23.     entry->release();  
  24. }  

InputDispatcher负责分发c++层获得的linux设备的按键事件,交由dispatcherPolicy,也就是NativeInputManager处理,NativeInputManager,通过Callbacks然后上报java层。

对于c++层如何获得的linux设备的按键事件,以及如何通过InputDispatcher分发这些事件感兴趣的,可以查看frameworks\base\services\input下的代码,可以先从InputManager.cpp的构造函数入手,或者查看网上相关文章。这里暂时不描述了。

相关文章推荐

Android Framework Java层是如何拦截并分发底层传送来的按键事件

按键事件首先通过PhoneWindowManager的interceptKeyBeforeDispatching方法被拦截,然后分发到应用层,一些系统事件:HOME,MENU,SEARCH,会在这里做...

android framework java层是如何拦截并分发底层传送来的按键事件

按键事件首先通过PhoneWindowManager的interceptKeyBeforeDispatching方法被拦截,然后分发到应用层,一些系统事件:HOME,MENU,SEARCH,会在这里做...

Android Framework层如何截获按键消息

代码位置: frameworks/base/services/input/InputDispatcher.cpp
  • I2Cbus
  • I2Cbus
  • 2014-11-14 12:44
  • 1856

Android Framework--事件分发

分发流程 我们知道system_server会启动各种服务,其中包括InputManagerService,IMS的native层对应者一个NativeInputManager。事件分发的起源就在这里...

Android Framework中修改鼠标按键功能

这是实际工作中遇到问题:要求可以在设置中修改鼠标上的Left、Middle、Right Button对应的功能,功能有4种:左键点击,右键点击,菜单键、返回键。按键和功能的对应关系可以用系统属性来存储...

Android Framework分析 ---- 1消息处理机制 java层

在Android的系统中,无论是App层还是native层都有处理任务需要放在单独的线程处理。各个线程直接的协调处理需要消息传递和处理。本文主要介绍一下Android的消息传递和处理的机制。

Android FrameWork——Touch事件派发过程详解

对于android的窗口window管理,一直感觉很混乱,总想找个时间好好研究,却不知如何入手,现在写的Touch事件派发过程详解,其实跟android的窗口window管理服务WindowManag...

Android FrameWork——Touch事件派发过程详解

对于Android的窗口window管理,一直感觉很混乱,总想找个时间好好研究,却不知如何入手,现在写的Touch事件派发过程详解,其实跟android的窗口window管理服务WindowManag...

Android FrameWork——Touch事件派发过程详解

对于android的窗口window管理,一直感觉很混乱,总想找个时间好好研究,却不知如何入手,现在写的Touch事件派发过程详解,其实跟android的窗口window管理服务WindowManag...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)