Step 8. NativeInputManager.setInputWindows
这个函数定义在frameworks/base/services/jni/com_android_server_InputManager.cpp 文件中:
  1. void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) {
  2. Vector<InputWindow> windows;
  3. jsize length = env->GetArrayLength(windowObjArray);
  4. for (jsize i = 0; i < length; i++) {
  5. jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
  6. if (! inputTargetObj) {
  7. break; // found null element indicating end of used portion of the array
  8. }
  9. windows.push();
  10. InputWindow& window = windows.editTop();
  11. bool valid = populateWindow(env, inputTargetObj, window);
  12. if (! valid) {
  13. windows.pop();
  14. }
  15. env->DeleteLocalRef(inputTargetObj);
  16. }
  17. mInputManager->getDispatcher()->setInputWindows(windows);
  18. }
        这个函数首先将Java层的Window转换成C++层的InputWindow,然后放在windows向量中,最后将这些输入窗口设置到InputDispatcher中去。
        Step 9. InputDispatcher.setInputWindows
        这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中:
  1. void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
  2. ......
  3. { // acquire lock
  4. AutoMutex _l(mLock);
  5. // Clear old window pointers.
  6. sp<InputChannel> oldFocusedWindowChannel;
  7. if (mFocusedWindow) {
  8. oldFocusedWindowChannel = mFocusedWindow->inputChannel;
  9. mFocusedWindow = NULL;
  10. }
  11. mWindows.clear();
  12. // Loop over new windows and rebuild the necessary window pointers for
  13. // tracking focus and touch.
  14. mWindows.appendVector(inputWindows);
  15. size_t numWindows = mWindows.size();
  16. for (size_t i = 0; i < numWindows; i++) {
  17. const InputWindow* window = & mWindows.itemAt(i);
  18. if (window->hasFocus) {
  19. mFocusedWindow = window;
  20. break;
  21. }
  22. }
  23. ......
  24. } // release lock
  25. ......
  26. }
        这里InputDispatcher的成员变量mFocusedWindow就代表当前激活的窗口的。这个函数首先清空mFocusedWindow,然后再通过一个for循环检查当前的输入窗口中的哪一个窗口是获得焦点的,获得焦点的输入窗口即为当前激活的窗口。
        这样,InputManager就把当前激活的Activity窗口保存在InputDispatcher中了,后面就可以把键盘消息分发给它来处理。
        回到Step 1中的ViewRoot.setView函数中,接下来就调用下面语句来注册键盘消息接收通道的一端到InputManager中去:
  1. mInputChannel = new InputChannel();
  2. try {
  3. res = sWindowSession.add(mWindow, mWindowAttributes,
  4. getHostVisibility(), mAttachInfo.mContentInsets,
  5. mInputChannel);
  6. } catch (RemoteException e) {
  7. ......
  8. } finally {
  9. ......
  10. }
        前面说过,这里的sWindowSession是WindowManagerService内部类Session的一个远程接口,通过它可以进入到WindowManagerService中去。
        Step 10. WindowManagerService.Session.add
        这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java 文件中:
  1. public class WindowManagerService extends IWindowManager.Stub
  2. implements Watchdog.Monitor {
  3. ......
  4. private final class Session extends IWindowSession.Stub
  5. implements IBinder.DeathRecipient {
  6. ......
  7. public int add(IWindow window, WindowManager.LayoutParams attrs,
  8. int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
  9. return addWindow(this, window, attrs, viewVisibility, outContentInsets,
  10. outInputChannel);
  11. }
  12. ......
  13. }
  14. ......
  15. }
        这里调用WindowManagerService类的addWindow函数来进一步执行操作。
        Step 11. WindowManagerService.addWindow
        这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java 文件中:
  1. public class WindowManagerService extends IWindowManager.Stub
  2. implements Watchdog.Monitor {
  3. ......
  4. public int addWindow(Session session, IWindow client,
  5. WindowManager.LayoutParams attrs, int viewVisibility,
  6. Rect outContentInsets, InputChannel outInputChannel) {
  7. ......
  8. WindowState win = null;
  9. synchronized(mWindowMap) {
  10. ......
  11. win = new WindowState(session, client, token,
  12. attachedWindow, attrs, viewVisibility);
  13. ......
  14. if (outInputChannel != null) {
  15. String name = win.makeInputChannelName();
  16. InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
  17. win.mInputChannel = inputChannels[0];
  18. inputChannels[1].transferToBinderOutParameter(outInputChannel);
  19. mInputManager.registerInputChannel(win.mInputChannel);
  20. }
  21. ......
  22. }
  23. ......
  24. }
  25. ......
  26. }

这里的outInputChannel即为前面在Step 1中创建的InputChannel,它不为NULL,因此,这里会通过InputChannel.openInputChannelPair函数来创建一对输入通道,其中一个位于WindowManagerService中,另外一个通过outInputChannel参数返回到应用程序中:

  1. inputChannels[1].transferToBinderOutParameter(outInputChannel);

创建输入通道之前,WindowManagerService会为当前Activity窗口创建一个WindowState对象win,用来记录这个Activity窗口的状态信息。当创建这对输入管道成功以后,也会把其中的一个管道保存在这个WindowState对象win的成员变量mInputChannel中,后面要注销这个管道的时候,就是从这个WindownState对象中取回这个管道的:

  1. win.mInputChannel = inputChannels[0];

接下来我们就看一下InputChannel.openInputChannelPair函数的实现。

本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966627,如需转载请自行联系原作者

Android应用程序键盘(Keyboard)消息处理机制分析(11)相关推荐

  1. Android系统中的Binder通信机制分析(7)- Java 层的 Binder 机制

    声明 其实对于Android系统Binder通信的机制早就有分析的想法,记得2019年6.7月份Mr.Deng离职期间约定一起对其进行研究的,但因为我个人问题没能实施这个计划,留下些许遗憾- 文中参考 ...

  2. Android应用程序键盘(Keyboard)消息处理机制分析(3)

    Step 15. Looper.pollOnce 这个函数定义在frameworks/base/libs/utils/Looper.cpp文件中,具体可以参考前面Android应用程序消息处理机制(L ...

  3. Android应用程序键盘(Keyboard)消息处理机制分析(12)

    Step 12. InputChannel.openInputChannelPair 这个函数定义在frameworks/base/core/java/android/view/InputChanne ...

  4. Android应用程序线程消息循环模型分析(5)

      从AsyncTask的实现可以看出,当我们第一次创建一个AsyncTask对象时,首先会执行下面静态初始化代码创建一个线程池sExecutor: private static final Bloc ...

  5. Android应用程序线程消息循环模型分析

    出自:http://blog.csdn.net/luoshengyang/article/details/6905587 我们知道,Android应用程序是通过消息来驱动的,即在应用程序的主线程(UI ...

  6. 以下未发布-Android的多线程以及异步消息处理机制,android移动开发基础案例教程源码

    1.Message: Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间进行数据交换.除了 what 字段,还可以使用 arg1 和 arg2 来携带整型数据,使用 ...

  7. Android应用程序键盘(Keyboard)消息处理机制分析(20)

    Step 24. InputQueue.dispatchKeyEvent 这个函数定义在frameworks/base/core/java/android/view/InputQueue.java文件 ...

  8. Android应用程序键盘(Keyboard)消息处理机制分析(26)

    Step 7. LocalWindowManager.removeViewImmediate 这个函数定义在frameworks/base/core/java/android/view/Window. ...

  9. Android应用程序键盘(Keyboard)消息处理机制分析(17)

    Step 11. InputDispatcher.dispatchOnceInnerLocked 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文 ...

  10. Android应用程序键盘(Keyboard)消息处理机制分析(14)

    3. InputManager分发键盘消息给应用程序的过程分析 在分析InputManager分发键盘消息给应用程序的过程之前,我们先假设现在没有键盘事件发生,因此,InputManager中的Inp ...

最新文章

  1. 数据结构实践——队列数组
  2. python3菜鸟教程中文-Python3 日期和时间
  3. 带密匙的php加密解密示例分享
  4. python电脑推荐_6款Python必备的可视化工具推荐
  5. 《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一2.4.6 为克隆使用序列化
  6. 对于 APM 用户的一次真实调查分析(下)
  7. 【Java】浅析Math类
  8. AE物体表面跟踪特效合成高级插件:Lockdown for Mac 支持ae2021
  9. Visual Studio中从应用程序中调试SQL脚本
  10. 最新sfc模拟器安卓汉化版_卡车模拟器山货运卡车3D游戏安卓最新版 v1.0 卡车模拟器山货运卡车3D游戏下载...
  11. 单片机c语言fft函数,单片机ADC采样FFT计算试验
  12. Linux Shell Weevely
  13. launcher3的具体学习
  14. Vue中插入jQuery插件
  15. php mongodb方法,PHP 操作mongodb api大部分方法
  16. 2112731-59-4,N-(Azido-PEG2)-N-Biotin-PEG3-acid末端羧酸可在活化剂(例如EDC或HATU)存在下与伯氨基反应
  17. AlarmClock
  18. react-native android 识别读取NFC卡信息
  19. 工作室课题—质因数2
  20. 网络安全工程师要学习哪些编程语言?哪里学网络安全知识可靠?

热门文章

  1. mysql front 视图_mysql 视图
  2. java发送qq消息_Java点餐系统和点餐小程序新加微信消息推送功能
  3. 21天Jenkins打卡Day6安装插件
  4. matlab电力系统潮流计算软件matpower_衡真课堂 | 电力系统稳态与暂态分析
  5. linux16.04设置网络,ubuntu16.04之后网络IP配置
  6. install openni2 on ubuntu
  7. 改进的EfficientNet-B4用于黑色素瘤检测
  8. 混淆矩阵(TP+FN+FP+TN)
  9. 【matlab】元胞数组(使用celldisp显示元胞数组)
  10. controller层没反应_一脚踏空就没命!57岁民警33层楼顶飞身救人