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. Java IO流之缓冲流

    一.缓冲流简介 二.BufferedInputStream 三.其他三种缓冲流

  2. Java中设计模式之工厂模式-4

    一.工厂模式由来 1)还没有工厂时代:假如还没有工业革命,如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿来用. 2)简单工厂模式:后来出现工业革命.用户不用去创建宝马车.因为客户有 ...

  3. SDWebImage源码阅读-第三篇

    这一篇讲讲不常用的一些方法. 1 sd_setImageWithPreviousCachedImageWithURL: placeholderImage: options: progress: com ...

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

    first-child选择器和last-child选择器 first-child指定第一个元素.last-child指定最后一个子元素. 例如: <!DOCTYPE html> <h ...

  5. Work Time Manager【开源项目】- 创建自己日志组件 2.0重构

    Hello all , 我又回来了 这次我们真是开始来聊聊开源项目里,小而有用的模块或者组件的开发思想. 同时,软件已经更新到1.60的版本了,支持新用户注册,可以不再使用统一的test账户了. 您可 ...

  6. Vulkan Tutorial 17 Rendering and presentation

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Setup 这一章节会把之前的所有内容进行整合.我们将会编写drawFrame函数, ...

  7. java编码详解

    举个例子 我们在开发过程中,特别是多种编码格式并存的情况下,很容易遇到乱码问题. 假如有一个GBK编码java文件,然后再使用-Dfile.encoding=GBK参数,写入的文件中哪些是乱码呢.那如 ...

  8. Linux下nginx+多个Tomcat负载均衡的实现

    博主原创,转载请注明. 由于项目需要,共创建了10个Tomcat端,由nginx负责转发.9个Tomcat端口分别是8080,11000,12000,13000,14000,15000,16000,1 ...

  9. EntityFramework连接SQLite

    EF很强大,可惜对于SQLite不支持CodeFirst模式(需要提前先设计好数据库表结构),不过对SQLite的数据操作还是很好用的. 先用SQLiteManager随便创建一个数据库和一张表:

  10. javac不是内部命令和外部命令

    因为系统不能识别javac命令,或者是因为你没有正确安装JDK. 在你的JDK所在的安装目录,在DOS环境里,比如是:C:\java>set path=c:\java1.4.1\bin 然后在c ...