美文网首页
Android之input InputChannel分析

Android之input InputChannel分析

作者: 锄禾豆 | 来源:发表于2022-01-26 18:59 被阅读0次

    分析代码实现情况

    代码位置
    frameworks/native/libs/input/InputTransport.cpp
    frameworks/base/core/jni/android_view_InputChannel.cpp
    frameworks/base/core/java/android/view/InputChannel.java
    

    案例InputChannel.openInputChannelPair

    1.java层InputChannel.openInputChannelPair

    android.view.InputChannel
    
    public final class InputChannel implements Parcelable {
        private static final String TAG = "InputChannel";
        
        ···
        
        @SuppressWarnings("unused")
        private long mPtr; // used by native code
        
        private static native InputChannel[] nativeOpenInputChannelPair(String name);
        
        ···
        
        /**
         * Creates a new input channel pair.  One channel should be provided to the input
         * dispatcher and the other to the application's input queue.
         * @param name The descriptive (non-unique) name of the channel pair.
         * @return A pair of input channels.  The first channel is designated as the
         * server channel and should be used to publish input events.  The second channel
         * is designated as the client channel and should be used to consume input events.
         */
        public static InputChannel[] openInputChannelPair(String name) {
            if (name == null) {
                throw new IllegalArgumentException("name must not be null");
            }
    
            if (DEBUG) {
                Slog.d(TAG, "Opening input channel pair '" + name + "'");
            }
            return nativeOpenInputChannelPair(name);
        }
        
        ···
    }
    

    这是双通道,一个给input服务的InputDispatcher使用,一个给Application使用

    2.native层nativeOpenInputChannelPair的实现

    android_view_InputChannel.cpp
    
    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);
    
        //创建客户端和服务端Channel
        sp<InputChannel> serverChannel;
        sp<InputChannel> clientChannel;
        status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
    
        if (result) {
            ···
            return NULL;
        }
    
        //创建大小为2的数组,channelPair
        jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
        if (env->ExceptionCheck()) {
            return NULL;
        }
    
        //创建服务端Channel对象
        jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
                new NativeInputChannel(serverChannel));
        if (env->ExceptionCheck()) {
            return NULL;
        }
    
        //创建客户端Channel对象
        jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
                new NativeInputChannel(clientChannel));
        if (env->ExceptionCheck()) {
            return NULL;
        }
    
        //将服务端和客户端Channel填充到数组channelPair
        env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
        env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
        return channelPair;
    }
    

    3.InputChannel::openInputChannelPair的实现
    创建native层的InputChannel通信对象

    InputTransport.cpp
    status_t InputChannel::openInputChannelPair(const String8& name,
            sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
        int sockets[2];
        if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
            ···
            return result;
        }
    
        int bufferSize = SOCKET_BUFFER_SIZE;
        //创建sockets数组,并且每一个元素都可读可写
        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    
        //真正初始化InputChannel对象
        String8 serverChannelName = name;
        serverChannelName.append(" (server)");
        outServerChannel = new InputChannel(serverChannelName, sockets[0]);
    
        String8 clientChannelName = name;
        clientChannelName.append(" (client)");
        outClientChannel = new InputChannel(clientChannelName, sockets[1]);
        return OK;
    }
    (1)真正创建native层的InputChannel对象,负责承载socket的通信
    
    InputChannel::InputChannel(const String8& name, int fd) :
            mName(name), mFd(fd) {
        ···
        //采用非阻塞型的O_NONBLOCK fcntl
        int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
        ···
    }
    

    4.android_view_InputChannel_createInputChannel

    android_view_inputChannel.cpp
    
    1)先分析NativeInputChannel对象的创建
    NativeInputChannel::NativeInputChannel(const sp<InputChannel>& inputChannel) :
        mInputChannel(inputChannel), mDisposeCallback(NULL) {
    }
    也就是NativeInputChannel就是重新包装了一下InputChannel
    
    2)android_view_InputChannel_createInputChannel
    static jobject android_view_InputChannel_createInputChannel(JNIEnv* env,
            NativeInputChannel* nativeInputChannel) {
        //创建java层的InputChannel对象
        jobject inputChannelObj = env->NewObject(gInputChannelClassInfo.clazz,
                gInputChannelClassInfo.ctor);
        //将java层对象和native层对象关联在一起
        if (inputChannelObj) {
            android_view_InputChannel_setNativeInputChannel(env, inputChannelObj, nativeInputChannel);
        }
        return inputChannelObj;
    }
    
    3)android_view_InputChannel_setNativeInputChannel
    static void android_view_InputChannel_setNativeInputChannel(JNIEnv* env, jobject inputChannelObj,
            NativeInputChannel* nativeInputChannel) {
        env->SetLongField(inputChannelObj, gInputChannelClassInfo.mPtr,
                 reinterpret_cast<jlong>(nativeInputChannel));
    }
    将java层的InputChannel对象中的mPtr和nativeInputChannel绑定在一起
    

    总结

    1.java层的InputChannel的真正创建工作由native层创建
    2.socket的初始化有native层的InputChannel创建,socket通信为非阻塞型
    3.InputChannel的运用:采用InputEventReceiver包装
    3.InputChannel.openInputChannelPair获取的数组
    inputChannel[0]是服务端,inputChannel[1]是客户端,由native初始化敲定
    

    相关文章

      网友评论

          本文标题:Android之input InputChannel分析

          本文链接:https://www.haomeiwen.com/subject/cgfwhrtx.html