openInputChannelPair(

 

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

Anonymous pipes 和Anonymous Shared Memory。

 

共享内存缓冲区大小,大概缓存20个触屏事件。

framework/base/include/ui/Input.h/* * Maximum number of pointers supported per motion event. * Smallest number of pointers is 1. * (We want at least 10 but some touch controllers obstensibly configured for 10 pointers * will occasionally emit 11.  There is not much harm making this constant bigger.) */#define MAX_POINTERS 16framework/base/libs/ui/InputTransport.cpp#define ROUND_UP(value, boundary) (((value) + (boundary) - 1) & ~((boundary) - 1))#define MIN_HISTORY_DEPTH 20// Must be at least sizeof(InputMessage) + sufficient space for pointer datastatic const int DEFAULT_MESSAGE_BUFFER_SIZE = ROUND_UP(        sizeof(InputMessage) + MIN_HISTORY_DEPTH                * (sizeof(InputMessage::SampleData) + MAX_POINTERS * sizeof(PointerCoords)),        4096);

 

 

 

JNI文件记录

InputQueue.java

android_view_InputQueue.cpp

android_view_InputChannel.cpp

 

InputManager.java

com_android_server_InputManager.cpp

 

framework/base/services/input/InputManager.h

framework/base/services/input/InputManager.cpp

 

framework/base/services/input/InputDispatcher.cpp

framework/base/services/input/InputDispatcher.cpp

 

framework/base/libs/ui/InputTransport.cpp

 

 

 

首先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 serverChannel;    sp 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& outServerChannel, sp& 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。

 

 

 

 

更多相关文章

  1. android 系统重启关机流程分析
  2. PopupWindow位置
  3. Android(安卓)Bitmap 改变的时候可能会抛出 java.lang.IllegalSt
  4. android javascript 调用activity
  5. Android之Handler的post注意事项
  6. 基于rk3288平台android5.1系统的wifi流程分析 ---- 打开wifi,扫描
  7. android sendevent模拟滑动点击事件
  8. android中使用SAX, DOM, 或者pull 来解析XML文档
  9. RadioGroup组与onCheckedChanged事件

随机推荐

  1. Android属性设置大全
  2. android 图片相关处理
  3. android 把TextView中的文字添加阴影效果
  4. Android 全局背景音乐
  5. Error while executing process D:\Andr
  6. android 解决小米手机Android Studio安装
  7. Android基础:什么是Android?
  8. Android:TextView跑马灯-详解
  9. android文件关联之mime type
  10. Android Compatibility zoom dialog 关闭