openInputChannelPair(

阅读本文的前提条件是知道匿名管道和匿名共享内存是怎么一回事,否则阅读相应的文章。

Anonymous pipes 和Anonymous Shared Memory。

首先ViewRoot的SetView方法中的关键地方:

第一处是创建:

 mInputChannel = new InputChannel();
try {
res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets,
mInputChannel);
}

第二处是注册:

 InputQueue.registerInputChannel(mInputChannel, mInputHandler,
Looper.myQueue());

创建部分的第一个方法InputChanel()构造函数是个空函数。重要的是第二个函数,

                    res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets,
mInputChannel);

这个函数调用的是系统服务,所谓的系统服务,就是运行在SYstem进程的服务程序。代码进入到了android系统服务进程的WindowManagerService类的Session类的add方法,下面是add方法:

        public int add(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
return addWindow(this, window, attrs, viewVisibility, outContentInsets,
outInputChannel);
}

add调用addWindow,下面进入addWindow,addWindow比较长,仅仅列出重要的几行代码:

            if (outInputChannel != null) {
String name = win.makeInputChannelName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
win.mInputChannel = inputChannels[0];
inputChannels[1].transferToBinderOutParameter(outInputChannel);
mInputManager.registerInputChannel(win.mInputChannel);
}

这里就牵涉到了匿名管道了,进入OpenInputChannelPair来看,调用了nativeOpenInputChannelPair,下面看nativeOpenInputChannelPair做了什么事情:

static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
jclass clazz, jstring nameObj) {
const char* nameChars = env->GetStringUTFChars(nameObj, NULL);
String8 name(nameChars);
env->ReleaseStringUTFChars(nameObj, nameChars);
sp<InputChannel> serverChannel;
sp<InputChannel> clientChannel;
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
}

最重要的是

status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);这一行

status_t InputChannel::openInputChannelPair(const String8& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
status_t result;
int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
if (serverAshmemFd < 0) {
result = -errno;
LOGE("channel '%s' ~ Could not create shared memory region. errno=%d",
name.string(), errno);
} else {
result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE);
if (result < 0) {
LOGE("channel '%s' ~ Error %d trying to set protection of ashmem fd %d.",
name.string(), result, serverAshmemFd);
} else {
// Dup the file descriptor because the server and client input channel objects that
// are returned may have different lifetimes but they share the same shared memory region.
int clientAshmemFd;
clientAshmemFd = dup(serverAshmemFd);
if (clientAshmemFd < 0) {
result = -errno;
LOGE("channel '%s' ~ Could not dup() shared memory region fd. errno=%d",
name.string(), errno);
} else {
int forward[2];
if (pipe(forward)) {
result = -errno;
LOGE("channel '%s' ~ Could not create forward pipe.  errno=%d",
name.string(), errno);
} else {
int reverse[2];
if (pipe(reverse)) {
result = -errno;
LOGE("channel '%s' ~ Could not create reverse pipe.  errno=%d",
name.string(), errno);
} else {
String8 serverChannelName = name;
serverChannelName.append(" (server)");
outServerChannel = new InputChannel(serverChannelName,
serverAshmemFd, reverse[0], forward[1]);
String8 clientChannelName = name;
clientChannelName.append(" (client)");
outClientChannel = new InputChannel(clientChannelName,
clientAshmemFd, forward[0], reverse[1]);
return OK;
}
::close(forward[0]);
::close(forward[1]);
}
::close(clientAshmemFd);
}
}
::close(serverAshmemFd);
}
outServerChannel.clear();
outClientChannel.clear();
return result;
}

这段代码又长又臭,总而言之就是创建用来【发送和接受信号】的接受和发送描述符,和生成用来【传递事件】的匿名共享内存,生成InputChannel对象。创建好之后,AddWindow方法通过BInder机制返回给【用户进程】。   客户端对应的是【应用程序】(读),服务端对应的是【InputDispatcher】(写)。

理解本段代码的关键是:代码中的 reverse和forward是相对于server来说的。对于server来说,后向管道用来接收,前向管道用来发送。函数pipe出来的值,数组的0索引对应的描述符是发送端。1对应的是接收端。

上面的介绍基本上就结束了。后面也许,我们更想知道的是这两个InputChannel如何通信的。一个在ViewRoot中,一个在InputDiapacher中。通信方式几本上就是,

InputReader(InputReader.cpp中)启动无限循环,读取一个事件,发送给InputDispacher,InputDispatcher把事件写入到共享内存,并通过管道发送信号给ViewRoot中的InputChannel,InputChannel收到信号后,通过InputConsumer的consume方法来把事件发送给VIewRoot中的InputChannel。

Android输入输出机制之来龙去脉相关推荐

  1. [置顶] Android输入输出机制之来龙去脉之前生后世

    记不住密码怎么办? http://a.app.qq.com/o/simple.jsp?pkgname=com.wa505.kf.epassword 先讲一下基本一般的输入处理方式的知识.一般的输入输出 ...

  2. Android输入输出机制之来龙去脉之前生后世

    密码太多记不了,怎么办? http://a.app.qq.com/o/simple.jsp?pkgname=com.wa505.kf.epassword 补充一下更详细的解说图,在输入输出系统中存在很 ...

  3. aidl使用_借助 AIDL 理解 Android Binder 机制——Binder 来龙去脉

    AIDL 是 Android Interface Definition Language(Android 接口定义语言)的缩写,它是 Android 进程间通信的接口语言.由于 Android 系统的 ...

  4. Android消息机制Handler用法

    这篇文章介绍了Android消息机制Handler用法总结,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 1.简述 Handler消息机制主要包括: Messa ...

  5. 【腾讯Bugly干货分享】经典随机Crash之二:Android消息机制

    为什么80%的码农都做不了架构师?>>>    本文作者:鲁可--腾讯SNG专项测试组 测试工程师 背景 承上经典随机Crash之一:线程安全 问题的模型 好几次灰度top1.top ...

  6. Android刷新机制-View绘制原理

    Android刷新机制-View绘制原理 Android刷新机制-SurfaceFlinger原理 Android刷新机制-Choreographer原理 一.概述 本文将从startActivity ...

  7. android消息池,回转寿司你一定吃过!——Android消息机制(构造)

    消息机制的故事寿司陈放在寿司碟上,寿司碟按先后顺序被排成队列送上传送带.传送带被启动后,寿司挨个呈现到你面前,你有三种享用寿司的方法. 将Android概念带入后,就变成了Android消息机制的故事 ...

  8. android handler的机制和原理_一文搞懂handler:彻底明白Android消息机制的原理及源码

    提起Android消息机制,想必都不陌生.其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行.本篇文章将由浅入深解析Android消息机制的运 ...

  9. Android渲染机制和丢帧分析

    http://blog.csdn.net/bd_zengxinxin/article/details/52525781 自己编写App的时候,有时会感觉界面卡顿,尤其是自定义View的时候,大多数是因 ...

最新文章

  1. 规格表管理之更新规格表数据
  2. Fleury算法找欧拉环游
  3. jax-rs jax-ws_什么是JAX-RS注释? (第3部分)
  4. 计算机视觉哪个方向最火?来看这篇综述《中国图像工程:2020》
  5. mysql 多个值求和_SQL优化大神玩转MySQL函数系列(2)LEAST,SUM的应用
  6. 活在贫困线之下的开源软件项目——开源的可持续性斗争
  7. doris历程_Doris简史-为分析而生的11年
  8. P-Associated-URI处理流程
  9. 服务器 'xxx' 上的 MSDTC 不可用。
  10. 如何像专业人士一样使用 Google 学术搜索
  11. 关于子函数的调用和终止
  12. 单片机霹雳灯双灯c语言,HOLTEK单片机-8LED霹雳灯
  13. 关闭WIN7交互式服务检测提示
  14. 12.0_[Java 多态]-多态/子类父类互转/基本引用类型互转/ instanceof 运算符
  15. fastadmin调用发送邮件验证码接口
  16. JS:利用函数,求任意三个数最大值,任意两个数的任意运算结果,判断任意数值是否为素数。
  17. 第14章 垃圾回收概述
  18. 生日快乐,我想念你们
  19. 数值计算方法(Numerical Methods)MATLAB实现(1)---Gauss消元法、Doolittle分解
  20. 「Python」数字推盘游戏-pygame

热门文章

  1. linux uwsgi 非root,ubuntu-除非root用户,否则uWSGI Emperor权限被拒绝
  2. 记录一下利用ffmpeg将avi转为mp4
  3. Opencv定义感兴趣区域
  4. class不生效 weblogic_weblogic下更改jsp不生效的解决办法
  5. JavaScript 面向对象实战思想
  6. 实现Spark集群部署 这些公司都经历了什么?
  7. JS Range 对象的使用
  8. 单选框-复选框重置的方法
  9. delphi回调函数
  10. ServletContext 与application的异同