原文链接:https://blog.csdn.net/qq_34211365/article/details/103243723
ViewRootImpl.java
/** * We have one child */ public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { ...... if ((mWindowAttributes.inputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { mInputChannel = new InputChannel();创建channel } res = mWindowSession.addToDisplay(mWindow, mSeq,mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel, mTempInsets);配置channel ...... }
WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq, LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, InsetsState outInsetsState) { ...... final WindowState win = new WindowState(this, session, client, token, parentWindow, appOp[0], seq, attrs, viewVisibility, session.mUid, session.mCanAddInternalSystemWindow); final boolean openInputChannels = (outInputChannel != null && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0); if (openInputChannels) { win.openInputChannel(outInputChannel); } ...... }
void openInputChannel(InputChannel outInputChannel) { if (mInputChannel != null) { throw new IllegalStateException("Window already has an input channel."); } String name = getName(); //创建InputChannelPair InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); //服务端InputChannel mInputChannel = inputChannels[0]; //客户端InputChannel mClientChannel = inputChannels[1]; mInputWindowHandle.token = mClient.asBinder(); if (outInputChannel != null) { //将客户端InputChannel发送回ViewRootImpl mClientChannel.transferTo(outInputChannel); mClientChannel.dispose(); mClientChannel = null; } else { // If the window died visible, we setup a dummy input channel, so that taps // can still detected by input monitor channel, and we can relaunch the app. // Create dummy event receiver that simply reports all events as handled. mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel); } //将服务端InputChannel注册到InputDispatcher mWmService.mInputManager.registerInputChannel(mInputChannel, mClient.asBinder()); }
openInputChannelPair
/** * 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); }
android_view_InputChannel.cpp
static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env, jclass clazz, jstring nameObj) { ScopedUtfChars nameChars(env, nameObj); std::string name = nameChars.c_str(); sp<InputChannel> serverChannel; sp<InputChannel> clientChannel; //创建Native层serverChannel和clientChannel status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel); ....... //创建java层数组,用在后面存放java层InputChannel,并返回 jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL); ...... //创建java层的server端的InputChannel对象 jobject serverChannelObj = android_view_InputChannel_createInputChannel(env, std::make_unique<NativeInputChannel>(serverChannel)); ...... //创建java层的clien端的InputChannel对象 jobject clientChannelObj = android_view_InputChannel_createInputChannel(env, std::make_unique<NativeInputChannel>(clientChannel)); ...... env->SetObjectArrayElement(channelPair, 0, serverChannelObj); env->SetObjectArrayElement(channelPair, 1, clientChannelObj); return channelPair; }
InputTransport.cpp
InputChannel::openInputChannelPair
status_t InputChannel::openInputChannelPair(const std::string& name, sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) { //一对socket数组 int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) { status_t result = -errno; ALOGE("channel '%s' ~ Could not create socket pair. errno=%d", name.c_str(), errno); outServerChannel.clear(); outClientChannel.clear(); return result; } int bufferSize = SOCKET_BUFFER_SIZE; //对两个socker分别设置 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)); std::string serverChannelName = name; //创建ServerChannel,后缀名+server serverChannelName += " (server)"; //通过setFd将sockets[0]和ServerChannel关联上 outServerChannel = new InputChannel(serverChannelName, sockets[0]); std::string clientChannelName = name; //创建ClientChannel,后缀名+client clientChannelName += " (client)"; //通过setFd将sockets[1]和ClientChannel关联上 outClientChannel = new InputChannel(clientChannelName, sockets[1]); return OK; } InputChannel::InputChannel(const std::string& name, int fd) : mName(name) { ...... setFd(fd); }
一对java层InputChannel,并将一对NativeInputChannel赋值给java层InputChannel的mPtr属性,并将server端InputChannel赋值给数组0,将client端InputChannel赋值给数组1,最后将数组返回给java层
WindowState
void openInputChannel(InputChannel outInputChannel) { if (mInputChannel != null) { throw new IllegalStateException("Window already has an input channel."); } String name = getName(); //native层返回的InputChannel数组,server端和cilent端 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); //server端InputChannel mInputChannel = inputChannels[0]; //client端InputChannel mClientChannel = inputChannels[1]; mInputWindowHandle.token = mClient.asBinder(); if (outInputChannel != null) { //将client端InputChannel传回到ViewRootImpl mClientChannel.transferTo(outInputChannel); mClientChannel.dispose(); mClientChannel = null; } else { // If the window died visible, we setup a dummy input channel, so that taps // can still detected by input monitor channel, and we can relaunch the app. // Create dummy event receiver that simply reports all events as handled. mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel); } //server端InputChannel注册到native层InputDispatcher mWmService.mInputManager.registerInputChannel(mInputChannel, mClient.asBinder()); }
InputChannel.java
/** * Transfers ownership of the internal state of the input channel to another * instance and invalidates this instance. This is used to pass an input channel * as an out parameter in a binder call. * @param other The other input channel instance. */ public void transferTo(InputChannel outParameter) { if (outParameter == null) { throw new IllegalArgumentException("outParameter must not be null"); } nativeTransferTo(outParameter); }
android_view_InputChannel.cpp
/* mClientChannel.transferTo(outInputChannel); */ //注意该方法参数中的otherObj和obj,otherObj代表传递下来的参数outInputChannel,obj代表调用此方法的对象mClientChannel static void android_view_InputChannel_nativeTransferTo(JNIEnv* env, jobject obj, jobject otherObj) { //当java层的outInputChannel的mPtr已经指向了一个NativeInputChannel时抛一个异常返回 if (android_view_InputChannel_getNativeInputChannel(env, otherObj) != NULL) { jniThrowException(env, "java/lang/IllegalStateException", "Other object already has a native input channel."); return; } //获取java层mClientChannel的mPtr属性,mPtr属性会指向一个NativeInputChannel对象,根据前面分析此时mClientChannel的mPtr指向client端的NativeInputChannel NativeInputChannel* nativeInputChannel = android_view_InputChannel_getNativeInputChannel(env, obj); android_view_InputChannel_setNativeInputChannel(env, otherObj, nativeInputChannel); android_view_InputChannel_setNativeInputChannel(env, obj, NULL); } static NativeInputChannel* android_view_InputChannel_getNativeInputChannel(JNIEnv* env, jobject inputChannelObj) { //jni方法,获取inputChannelObj对象的gInputChannelClassInfo.mPtr属性 jlong longPtr = env->GetLongField(inputChannelObj, gInputChannelClassInfo.mPtr); return reinterpret_cast<NativeInputChannel*>(longPtr); } static void android_view_InputChannel_setNativeInputChannel(JNIEnv* env, jobject inputChannelObj, NativeInputChannel* nativeInputChannel) { //jni方法,将inputChannelObj的gInputChannelClassInfo.mPtr属性赋值为nativeInputChannel env->SetLongField(inputChannelObj, gInputChannelClassInfo.mPtr, reinterpret_cast<jlong>(nativeInputChannel)); }
上面的方法主要作用就是将mClientChannel的mPtr属性赋值给outInputChannel,并将mClientChannel的mPtr赋值为NULL,这样就实现了将mClientChannel与outInputChannel互换,outInputChannel是ViewRootImpl的传递过来的mInputChannel,达到了将mClientChannel传递个应用客户端的目的。
InputManagerService.java
/** * Registers an input channel so that it can be used as an input event target. * @param inputChannel The input channel to register. * @param inputWindowHandle The handle of the input window associated with the * input channel, or null if none. */ public void registerInputChannel(InputChannel inputChannel, IBinder token) { if (inputChannel == null) { throw new IllegalArgumentException("inputChannel must not be null."); } if (token == null) { token = new Binder(); } inputChannel.setToken(token); //native方法 nativeRegisterInputChannel(mPtr, inputChannel, Display.INVALID_DISPLAY); }
com_android_server_input_InputManagerService.cpp
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr, jobject inputChannelObj, jint displayId) { //ptr是java层InputManagerService中的mPtr属性,在InputManagerService初始化时指向了NativeInputManager NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); //通过java层传下来的inputChannels[0]获取到Native层的server端InputChannel sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj); if (inputChannel == nullptr) { throwInputChannelNotInitialized(env); return; } //注册inputChannel status_t status = im->registerInputChannel(env, inputChannel, displayId); if (status) { std::string message; message += StringPrintf("Failed to register input channel. status=%d", status); jniThrowRuntimeException(env, message.c_str()); return; } //设置handleInputChannelDisposed回调 android_view_InputChannel_setDisposeCallback(env, inputChannelObj, handleInputChannelDisposed, im); }
status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */, const sp<InputChannel>& inputChannel, int32_t displayId) { ATRACE_CALL(); return mInputManager->getDispatcher()->registerInputChannel( inputChannel, displayId); }
//InputDispatcher.h // All registered connections mapped by channel file descriptor. KeyedVector<int, sp<Connection> > mConnectionsByFd GUARDED_BY(mLock); status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, int32_t displayId) { { // acquire lock ...... //创建Connection对象 sp<Connection> connection = new Connection(inputChannel, false /*monitor*/); //获取之前通过setFd存入的socket[0] int fd = inputChannel->getFd(); //将fd和connection关联,后续InputDispatch通过fd可以获取对应connection,通过connection获取server InputChannel和client InputChannel通信从而将事件分发到对应的应用窗口 mConnectionsByFd.add(fd, connection); mInputChannelsByToken[inputChannel->getToken()] = inputChannel; //将fd添加到Looper线程进行监听,在收到对端相应事件之后回调handleReceiveCallback mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); } // release lock // Wake the looper because some connections have changed. mLooper->wake(); return OK; }
从java层传下来的inputChannels[0]就已经注册到了InputDispatcher并且将对应的Fd添加到了InputDispatcher的Loop进行监听,并且传进去了一个回调handleReceiveCallback,应用端窗口处理完输入事件之后回调此方法。
handleReceiveCallback
ViewRootImpl.java
在上面流程addToDisplay方法执行完之后ViewRootImpl中的mInputChannel已经变成了client端的InputChannel即inputChannels[1]
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { ...... mInputChannel = new InputChannel(); res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel, mTempInsets); ...... if (mInputChannel != null) { if (mInputQueueCallback != null) { mInputQueue = new InputQueue(); mInputQueueCallback.onInputQueueCreated(mInputQueue); } mInputEventReceiver = new WindowInputEventReceiver(mInputChannel, Looper.myLooper()); } ...... }
WindowInputEventReceiver
/** * Creates an input event receiver bound to the specified input channel. * * @param inputChannel The input channel. * @param looper The looper to use when invoking callbacks. */ public InputEventReceiver(InputChannel inputChannel, Looper looper) { if (inputChannel == null) { throw new IllegalArgumentException("inputChannel must not be null"); } if (looper == null) { throw new IllegalArgumentException("looper must not be null"); } mInputChannel = inputChannel; //UI线程的messagequeue mMessageQueue = looper.getQueue(); //native方法,将自己,client端的InputChannel和UI线程的messagequeue传进去 mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this), inputChannel, mMessageQueue); mCloseGuard.open("dispose"); }
android_view_InputEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject inputChannelObj, jobject messageQueueObj) { //见过很多次了该方法,通过传下来的cilent端的InputChannel获取对应的native层InputChannel sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj); if (inputChannel == NULL) { jniThrowRuntimeException(env, "InputChannel is not initialized."); return 0; } //通过传下来的messagequeue获取对于native层的messagequeue sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); if (messageQueue == NULL) { jniThrowRuntimeException(env, "MessageQueue is not initialized."); return 0; } //创建NativeInputEventReceiver sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env, receiverWeak, inputChannel, messageQueue); status_t status = receiver->initialize(); if (status) { String8 message; message.appendFormat("Failed to initialize input event receiver. status=%d", status); jniThrowRuntimeException(env, message.string()); return 0; } receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object return reinterpret_cast<jlong>(receiver.get()); }
创建NativeInputEventReceiver
//给NativeInputEventReceiver成员变量赋值 NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env, jobject receiverWeak, const sp<InputChannel>& inputChannel, const sp<MessageQueue>& messageQueue) : mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)), mInputConsumer(inputChannel), mMessageQueue(messageQueue), mBatchedInputEventPending(false), mFdEvents(0) { } }
status_t NativeInputEventReceiver::initialize() { setFdEvents(ALOOPER_EVENT_INPUT); return OK; } void NativeInputEventReceiver::setFdEvents(int events) { if (mFdEvents != events) { mFdEvents = events; //获取client端InputChannel的Fd即socket[1] int fd = mInputConsumer.getChannel()->getFd(); if (events) { //将fd添加到UI线程进行监听,回调传的this mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL); } else { mMessageQueue->getLooper()->removeFd(fd); } } }
到此client端的Fd也已经传递到了UI线程进行监听,InputDispatch与ViewRootImpl的socket连接已经建立。