Android之input InputChannel分析

2022-01-26  本文已影响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初始化敲定
上一篇下一篇

猜你喜欢

热点阅读