Android系统--输入系统(十六)APP跟输入系统建立联系_InputChannel和Connection

0. 核心:socketpair机制

1. 回顾Dispatch处理过程:

1.1 放入队列前稍加处理

  • 分类:Global Key/System Key/User Key
  • 处理紧急事件(比如来电的时候按下音量键静音)

1.2 InputReader线程将读到的输入事件稍加处理后放入mInboundQueue队列中,接着唤醒Dispatch线程

1.3 Dispatch从mInboundQueue队列中将输入事件取出,并稍加处理。

  • 对于Global Key/System Key按键处理:放入mCommandQueue队列中,依次处理,处理之后就release
  • 对于User Key,放入队列:查找目标APP,得到Connection,放入其OutBoundQueue队列中,稍后取出处理

2. 引入--如何找出目标应用程序,输入系统和应用程序如何建立联系?

PC和安卓系统都是运行着多个应用程序,但是只有屏幕最前面的应用程序才可以接收到输入事件,谁来告诉输入事件哪个是运行在屏幕最前面的应用程序呢?

2.1 引入WindowServiceManager窗口管理服务

  • 对于每一个应用程序,WindowServiceManager都有一个结构体WindowSate来表示该应用程序。假设新启动一个APP,通过binder通信,调用addToDisplay,会导致AddWindow被调用,AddWindow创建了WindowSate表示该应用程序,接着创建一个socketpair得到两个文件句柄fd0和fd1,fd1直接返回给应用程序,fd0将其封装为InputChannel类,一方面InputChannel会放进该APPWindowState中,另外一方面,他会将InputChannel注册给InputDispatch。

2.2 Dispatch线程

  • InputDispatch线程中里面有KeyedVector包含含有多个connection,这些connection可以通过注册实现,创建一个connection(含有InputChannel,InputChannel含有文件句柄fd),将创建好的connection放入Vector当中。
// All registered connections mapped by channel file descriptor.
KeyedVector<int, sp<Connection> > mConnectionsByFd;

2.3 引入connection

  • 对于每一个能够接受输入事件应用程序,在InputDispatch当中都有一个connection。假设还有一个应用程序APP,在WindowServiceManager中也有一个WindowState,在InputDispatch中也有一个对应的connection,放入Vector容器中,在connection中含有InputChannel和fd,其中fd来自Socketpair的fd0,另外一个fd1通过Binder通信返回给APP4。这样子InputDispatch线程想把输入事件发送给APP时候,先要找出当前在屏幕最前面的应用程序,然后从vector容器中找到他的connection,然后将数据写入fd当中既可。

2.4 总结

  • Dispatch线程从输入事件中读到数据后,可以通过Vector当中找出某个connection,把输入事件放入fd当中,另外一个应用程序可以从另外一个文件句柄中得到输入事件,将得到的文件句柄封装为InputChannel,再封装为WindowInputEventReceiver,最后把fd放入Looper中,使用Epoll机制查询等待数据,具体可以见下面关系图。

2.5 补充

  • InputReader线程、InputDispatch线程和WindowServiceManager都处于System进程当中,故这三个线程可以直接通信不需要Binder介入,而APP如果想跟这三个线程通信则需要通过Binder机制来实现或者通过事先建立好的Socketpair再通过Binder将文件句柄返回给APP,故其文件句柄可能发生变化。

3. APP获得SocketPair的fd过程分析

  • 发起addToDisplay的操作
ViewRootImpl.java
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mInputChannel);
  • 导致同文件下的onTransact被调用
IWindowSession.java
mRemote.transact(Stub.TRANSACTION_addToDisplay, _data, _reply, 0);
  • 根据code值调用本地的addToDisplay
IWindowSession.java
int _result = this.addToDisplay(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6);
- 得到两个文件句柄
Session.java
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets,
InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outInputChannel);
}
WindowManagerService.java
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
- 把fd1写给InputChanne
WindowManagerService.java
inputChannels[1].transferTo(outInputChannel); //outInputChannel含有fd1,实际上就是arg6
  • 根据_arg6的返回结果,把fd写给Binder驱动程序
IWindowSession.java
_arg6.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- 最终调用该函数把fd写入bind驱动中
android_view_InputChannel.cpp
parcel->writeDupFileDescriptor(inputChannel->getFd());
  • 远程操作之后,从驱动程序读出fd
outContentInsets.readFromParcel(_reply);
- 从Binder驱动中读出fd
android_view_InputChannel.cpp
int rawFd = parcel->readFileDescriptor();
int dupFd = dup(rawFd);

4. 具体调用过程时序图

具体源码可以根据下面的时序图进行具体分析。注:引用韦东山老师

Android系统--输入系统(十六)APP跟输入系统建立联系_InputChannel和Connection的更多相关文章

  1. 第十六篇:Linux系统编程中环境变量的使用

    前言 在 UNIX Like 系统中,存有各类系统/应用程序的环境变量,可通过修改之改变系统/应用程序的执行效果:除此之外,用户还可以定义自己的环境变量,供自己写的程序使用. 本文将说明如何在程序中设 ...

  2. 第三十六节,os系统级别操作模块

    在使用os模块时需要先 import os 引入模块 os.getcwd()模块函数 功能:获取当前工作目录,即当前python脚本工作的目录路径[无参] 使用方法:os.getcwd() 格式如:a ...

  3. Android笔记(二十六) Android中的广播——BroadcastReceiver

    为了方便进行系统级别的消息通知,Android有一套类似广播的消息机制,每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收自己所关心的广播内容,这些广播可能是来自于系统,也可能是来自于 ...

  4. Android开发系列(十六):【Android小游戏成语连连看】第二篇

    写的晚了,在分工个Z市高中的一个成绩查询的系统,原系统居然是用VB写的,我不得不佩服原本写系统的那位哥们真能耐得住. 明天搭建下SVN就等着先发project款然后開始项目了.想想有工资进账,心里也为 ...

  5. Android核心分析之十六Android电话系统-概述篇

    Android电话系统之概述篇 首先抛开Android的一切概念来研究一下电话系统的最基本的描述.我们的手机首先用来打电话的,随后是需要一个电话本,随后是PIM,随后是网络应用,随后是云计算,随后是想 ...

  6. 【转】Pro Android学习笔记(十六):用户界面和控制(4):ImageView控件

    目录(?)[-] XML片段 代码设置ImageView ImageView是基础的控件,它是android.widget.ImageView的继承类. XML片段      <LinearLa ...

  7. Android学习笔记(十六) ContentProvider

    1.相关概念 ContentProvider:不同应用程序之间进行数据交换的标准API:程序“暴露”数据的方法. ContentResolver:一个程序访问另一个程序被“暴露”的数据的方法. Uri ...

  8. Android笔记(五十六) Android四大组件之一——ContentProvider,实现自己的ContentProvider

    有时候我们自己的程序也需要向外接提供数据,那么就需要我们自己实现ContentProvider. 自己实现ContentProvider的话需要新建一个类去继承ContentProvider,然后重写 ...

  9. Android笔记(四十六) Android中的数据存储——XML(二)PULL解析

    PULL 的工作原理: XML pull提供了开始元素和结束元素.当某个元素开始时,可以调用parser.nextText()从XML文档中提取所有字符数据.当解析到一个文档结束时,自动生成EndDo ...

随机推荐

  1. Vulkan Tutorial 12 Fixed functions

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 早起的图形API在图形渲染管线的许多阶段提供了默认的状态.在Vulkan中,从vie ...

  2. Mac OS 的命令行 总结

    du 命令 查看目录下所有文件的大小: du -sh * ls 命令 直接显示当前目录下的所有的非隐藏文件: ls // 怎么在文章中显示不出来?? 显示当前目录下的所有的文件(包括隐藏的): ls ...

  3. MVC 树节点Table格式授权

    这几夜心里颇不平静, 奈何 JS水平有限,前台效果耗时四天,后台传值一天,直至昨夜丑时测试初步完成,其实就是一个给tree来授权,网上开源的插件很多,如treejs.easyui 等等,只是这里授权稍 ...

  4. CSS3学习系列之选择器(四)

    使用选择器来插入文字 css2中,使用before选择器在元素前面插入内容,使用after选择器在元素后面插入内容,在选择器的content属性中定义要插入的内容.将content属性值设定为none ...

  5. 前端学习数据库MYSQL

    这篇文章主要写了 1.数据库MYSQL 2.基本上会遇到的所有SQL语句 数据库可视化软件------Navicat 数据库里边存放的是表,表与表之间是有关联的,而且可以对表进行相关操作(增,删,改, ...

  6. 关于Handler的理解,子线程不能更新UI的纠正和回调的思考

    开发Android这么久了,总会听到有人说:主线程不能访问网络,子线程不能更新UI.Android的主线程的确不能长时间阻塞,但是子线程为什么不能更新UI呢?今天把这些东西整理,顺便在子线程更新UI. ...

  7. CSS的小三角

    上三角▲ width: 0; height: 0; line-height: 0; font-size: 0; border-width: 10px; border-style: solid; bor ...

  8. 理解容器之间的连通性 - 每天5分钟玩转 Docker 容器技术(34)

    通过前面小节的实践,当前 docker host 的网络拓扑结构如下图所示,今天我们将讨论这几个容器之间的连通性. 两个 busybox 容器都挂在 my_net2 上,应该能够互通,我们验证一下: ...

  9. oracle数据库的编码

    --oracle数据库的编码select * from nls_database_parameters where parameter ='NLS_CHARACTERSET';--oracle客户端编 ...

  10. Swift计算字符数量

    通过调用全局 countElements 函数并将字符串作为参数进行传递可以获取该字符串的字符数量. let unusualMenagerie = "Koala