上文说到,在InputChannel被创建后,紧接着就是注册InputChannel,看以下代码:
if (outInputChannel != null) {
String name = win.makeInputChannelName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
win.mInputChannel = inputChannels[0];
inputChannels[1].transferToBinderOutParameter(outInputChannel);
mInputManager.registerInputChannel(win.mInputChannel);
}注意到被注册的是win.mInputChannel,也就是inputChannels[0],inputChannels[0]是什么?再看创建InputChannel的过程,发现以下代码:
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);
if (result) {
LOGE("Could not open input channel pair. status=%d", result);
jniThrowRuntimeException(env, "Could not open input channel pair.");
return NULL;
}
// TODO more robust error checking
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
new NativeInputChannel(serverChannel));
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
new NativeInputChannel(clientChannel));
jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
return channelPair;
}倒数第三行表明,inputChannels[0]是serverChannel,也就是说,在WmS中注册的仅仅是serverChannel,那么clientChannel需要注册吗?什么时候注册的?
我们一直在说,应用程序创建窗口时,通过ViewRoot调用WmS的session的addWindow方法创建窗口,来看ViewRoot的代码,在frameworks/base/core/java/android.view.ViewRoot.java的第497行,发现如下代码:
res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets,
mInputChannel);判断此代码即是使用session添加Window的方法,接着往下看,发现以下代码:
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue(mInputChannel);
mInputQueueCallback.onInputQueueCreated(mInputQueue);
} else {
InputQueue.registerInputChannel(mInputChannel, mInputHandler,
Looper.myQueue());
}InputQueue.registerInputChannel即为客户端注册InputChannel的方法,也就是说,在ViewRoot中IPC调用addWindow()返回后,接下来就需要把该InputChannel注册到本线程中,而ViewRoot通过InputQueue.registerInputChannel注册InputChannel。
InputQueue.registerInputChannel方法如下所示:
/**
* Registers an input channel and handler.
* @param inputChannel The input channel to register.
* @param inputHandler The input handler to input events send to the target.
* @param messageQueue The message queue on whose thread the handler should be invoked.
* @hide
*/
public static void registerInputChannel(InputChannel inputChannel, InputHandler inputHandler,
MessageQueue messageQueue) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (inputHandler == null) {
throw new IllegalArgumentException("inputHandler must not be null");
}
if (messageQueue == null) {
throw new IllegalArgumentException("messageQueue must not be null");
}
synchronized (sLock) {
if (DEBUG) {
Slog.d(TAG, "Registering input channel '" + inputChannel + "'");
}
nativeRegisterInputChannel(inputChannel, inputHandler, messageQueue);
}
}你会发现它其实主要调用了nativeRegisterInputChannel,也就是android_view_InputQueue的registerInputChannel方法来完成注册,该方法如下 所示:
status_t NativeInputQueue::registerInputChannel(JNIEnv* env, jobject inputChannelObj,
jobject inputHandlerObj, jobject messageQueueObj) {
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
if (inputChannel == NULL) {
LOGW("Input channel is not initialized.");
return BAD_VALUE;
}
#if DEBUG_REGISTRATION
LOGD("channel '%s' - Registered", inputChannel->getName().string());
#endif
sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
{ // acquire lock
AutoMutex _l(mLock);
if (getConnectionIndex(inputChannel) >= 0) {
LOGW("Attempted to register already registered input channel '%s'",
inputChannel->getName().string());
return BAD_VALUE;
}
uint16_t connectionId = mNextConnectionId++;
sp<Connection> connection = new Connection(connectionId, inputChannel, looper);
status_t result = connection->inputConsumer.initialize();
if (result) {
LOGW("Failed to initialize input consumer for input channel '%s', status=%d",
inputChannel->getName().string(), result);
return result;
}
connection->inputHandlerObjGlobal = env->NewGlobalRef(inputHandlerObj);
int32_t receiveFd = inputChannel->getReceivePipeFd();
mConnectionsByReceiveFd.add(receiveFd, connection);
looper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
} // release lock
android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
handleInputChannelDisposed, this);
return OK;
}这段代码与serverChannel的区别不大,不再细述。
本文详细解析了 Android 系统中 InputChannel 的注册过程,包括 server 和 client 端的注册机制,并介绍了 ViewRoot 如何通过 InputQueue.registerInputChannel 方法完成客户端 InputChannel 的注册。
1万+

被折叠的 条评论
为什么被折叠?



