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初始化敲定