高清图:www.plantuml.com/plantuml/pn…
framework/base/core/java/android/view/ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
synchronized (this) {
if (mView == null) {
mView = view;
.....
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();
InputChannel inputChannel = null;
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
// step1 创建inputChannel
inputChannel = new InputChannel();
}
mForceDecorViewVisibility = (mWindowAttributes.privateFlags
& PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
try {
// step2 调用WMS addWindow
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
mTempControls);
} catch (RemoteException e) {
} finally {
}
.......
// wms对inputChannel赋值之后,
if (inputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
// step3 创建mInputEventReceiver,用于注册client端的inputChannel,传的是主线程的looper
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
Looper.myLooper());
}
view.assignParent(this);
......
// step4 创建消息回调的InputStage链
// Set up the input pipeline.
CharSequence counterSuffix = attrs.getTitle();
mSyntheticInputStage = new SyntheticInputStage();
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);
mFirstInputStage = nativePreImeStage;
mFirstPostImeInputStage = earlyPostImeStage;
}
}
}
该方法是显示View的入口,ViewRootImpl中的inputChannel对象是空对象,要经过WMS赋值才有意义,赋值之后会将client的inputChannel注册到主线程的looper中。
step2
framework/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
int displayId, int requestUserId, InsetsState requestedVisibility,
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls) {
......
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], attrs, viewVisibility, session.mUid, userId,
session.mCanAddInternalSystemWindow);
final boolean openInputChannels = (outInputChannel != null
&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
step5 创建InputChannel
win.openInputChannel(outInputChannel);
}
.......
win.attach();
mWindowMap.put(client.asBinder(), win);
boolean focusChanged = false;
if (win.canReceiveKeys()) {
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /*updateInputWindows*/);
}
step6 调整当前获取焦点的窗口信息
if (focusChanged) {
displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
false /*updateInputWindows*/);
}
displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
......
}
return res;
}
该函数创建ViewRootImpl对应的WindowState,加入到mWindowMap,WindowState执行了openInputChannel(outInputChannel);方法来创建InputChannel,看下这个方法。
step5
framework/base/services/core/java/com/android/server/wm/WindowState.java
void openInputChannel(InputChannel outInputChannel) {
String name = getName();
// step7 InputManager创建inputChannel
mInputChannel = mWmService.mInputManager.createInputChannel(name);
mInputChannelToken = mInputChannel.getToken();
// 保存mInputChannelToken到mInputWindowHandle
mInputWindowHandle.setToken(mInputChannelToken);
mWmService.mInputToWindowMap.put(mInputChannelToken, this);
if (outInputChannel != null) {
// 给client的inputchannel赋值
mInputChannel.copyTo(outInputChannel);
} else {
}
}
该方法就调用IMS来真正创建InputChannel
下面来分析一下IMS的逻辑 framework/base/services/core/java/com/android/server/input/InputManagerService.java
/**
* Creates an input channel to be used as an input event target.
*
* @param name The name of this input channel
*/
public InputChannel createInputChannel(String name) {
return nativeCreateInputChannel(mPtr, name);
}
framework/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jobject nativeCreateInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr,
jstring nameObj) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
ScopedUtfChars nameChars(env, nameObj);
std::string name = nameChars.c_str();
// step8 调用ims#createInputChannel
base::Result<std::unique_ptr<InputChannel>> inputChannel = im->createInputChannel(env, name);
// step9 根据native的inputChannel 创建java层的inputChannel对象,
jobject inputChannelObj =
android_view_InputChannel_createJavaObject(env, std::move(*inputChannel));
if (!inputChannelObj) {
return nullptr;
}
android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
handleInputChannelDisposed, im);
return inputChannelObj;
}
base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(
JNIEnv* /* env */, const std::string& name) {
ATRACE_CALL();
return mInputManager->getDispatcher()->createInputChannel(name);
}
调用了InputDispatcher创建createInputChannel
framework/native/services/inputflinger/dispatcher/InputDispatcher.cpp
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
std::unique_ptr<InputChannel> serverChannel;
std::unique_ptr<InputChannel> clientChannel;
// step10 创建socketpair,对serverChannel、clientChannel赋值
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
{ // acquire lock
std::scoped_lock _l(mLock);
const sp<IBinder>& token = serverChannel->getConnectionToken();
// 拿到serverChannel的fd
int fd = serverChannel->getFd();
//将serverChannel包装成Connection
sp<Connection> connection =
new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);
// 保存到mConnectionsByToken
mConnectionsByToken.emplace(token, connection);
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
// step11 将serverChannel注册到inputDispatcher的mLooper
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);
} // release lock
// Wake the looper because some connections have changed.
// 唤醒dispatcher的looper
mLooper->wake();
//返回clientChannel
return clientChannel;
}
static status_t openInputChannelPair(const std::string& name,
std::shared_ptr<InputChannel>& serverChannel,
std::unique_ptr<InputChannel>& clientChannel) {
std::unique_ptr<InputChannel> uniqueServerChannel;
status_t result = InputChannel::openInputChannelPair(name, uniqueServerChannel, clientChannel);
serverChannel = std::move(uniqueServerChannel);
return result;
}
framework/native/libs/input/InputTransport.cpp
status_t InputChannel::openInputChannelPair(const std::string& name,
std::unique_ptr<InputChannel>& outServerChannel,
std::unique_ptr<InputChannel>& outClientChannel) {
int sockets[2];
// linux的socketpair 全双工socket通信
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
status_t result = -errno;
ALOGE("channel '%s' ~ Could not create socket pair. errno=%s(%d)", name.c_str(),
strerror(errno), errno);
outServerChannel.reset();
outClientChannel.reset();
return result;
}
int bufferSize = SOCKET_BUFFER_SIZE;
//设置socket参数,读写缓冲区的上限
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));
sp<IBinder> token = new BBinder();
// serverChannelName以(server)结尾
std::string serverChannelName = name + " (server)";
android::base::unique_fd serverFd(sockets[0]);
outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);
// clientChannelName以(client)结尾
std::string clientChannelName = name + " (client)";
android::base::unique_fd clientFd(sockets[1]);
outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
return OK;
}
std::unique_ptr<InputChannel> InputChannel::create(const std::string& name,
android::base::unique_fd fd, sp<IBinder> token) {
const int result = fcntl(fd, F_SETFL, O_NONBLOCK);
if (result != 0) {
LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(),
strerror(errno));
return nullptr;
}
// using 'new' to access a non-public constructor
// 直接new InputChannel
return std::unique_ptr<InputChannel>(new InputChannel(name, std::move(fd), token));
}
创建socketpair,并且把server端的fd注册到InputDispatcher的looper中。 创建InputChannel传入了channelname,各自的fd 和相同的token,到这里两个inputChannel就创建好了,继续回到step8,继续往下执行,将native的inputchannel返回给java层。
frameworks/base/core/jni/android_view_InputChannel.cpp
jobject android_view_InputChannel_createJavaObject(JNIEnv* env,
std::unique_ptr<InputChannel> inputChannel) {
std::string name = inputChannel->getName();
jlong ptr = android_view_InputChannel_createInputChannel(env, std::move(inputChannel));
jobject javaInputChannel =
env->NewObject(gInputChannelClassInfo.clazz, gInputChannelClassInfo.mCtor);
......
// 调用java层的SetNativeInputChannel方法,设置mptr属性值
env->CallVoidMethod(javaInputChannel, gInputChannelClassInfo.mSetNativeInputChannel, ptr);
if (env->ExceptionOccurred()) {
ALOGE("Failed to set native ptr to the Java InputChannel for channel %s.",
inputChannel->getName().c_str());
return nullptr;
}
return javaInputChannel;
}
static jlong android_view_InputChannel_createInputChannel(
JNIEnv* env, std::unique_ptr<InputChannel> inputChannel) {
std::unique_ptr<NativeInputChannel> nativeInputChannel =
std::make_unique<NativeInputChannel>(std::move(inputChannel));
return reinterpret_cast<jlong>(nativeInputChannel.release());
}
创建了NativeInputChannel,持有inputchannel的指针,然后调用java层InputChannel对象的构造函数gInputChannelClassInfo保存了java层InputChannel的类信息。
int register_android_view_InputChannel(JNIEnv* env) {
int res = RegisterMethodsOrDie(env, "android/view/InputChannel", gInputChannelMethods,
NELEM(gInputChannelMethods));
jclass clazz = FindClassOrDie(env, "android/view/InputChannel");
gInputChannelClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
gInputChannelClassInfo.mCtor =
GetMethodIDOrDie(env, gInputChannelClassInfo.clazz, "<init>", "()V");
gInputChannelClassInfo.mSetNativeInputChannel =
GetMethodIDOrDie(env, gInputChannelClassInfo.clazz, "setNativeInputChannel", "(J)V");
gInputChannelClassInfo.mPtr = GetFieldIDOrDie(env, gInputChannelClassInfo.clazz, "mPtr", "J");
return res;
}
所以返回给java层的是NativeInputChannel对象的地址。
native执行完了,返回到WindowState的openInputChannel方法,我们继续看这个方法
framework/base/services/core/java/com/android/server/wm/WindowState.java
void openInputChannel(InputChannel outInputChannel) {
String name = getName();
// InputManager创建inputChannel
mInputChannel = mWmService.mInputManager.createInputChannel(name);
// 从这边继续执行
mInputChannelToken = mInputChannel.getToken();
// 保存mInputChannelToken到mInputWindowHandle
mInputWindowHandle.setToken(mInputChannelToken);
mWmService.mInputToWindowMap.put(mInputChannelToken, this);
if (outInputChannel != null) {
// 给client的inputchannel赋值
mInputChannel.copyTo(outInputChannel);
} else {
}
}
拿到inputChannel的token,这个token是server和client公用的,保存到属性mInputWindowHandle,并且把token和windowState的对应关系保存到wms的mInputToWindowMap,最后给outInputChannel赋值
frameworks/base/core/java/android/view/InputChannel.java
/**
* Creates a copy of this instance to the outParameter. 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 copyTo(InputChannel outParameter) {
if (outParameter == null) {
throw new IllegalArgumentException("outParameter must not be null");
}
if (outParameter.mPtr != 0) {
throw new IllegalArgumentException("Other object already has a native input channel.");
}
// 就是把native层的NativeInputChannel的地址保存到mptr
outParameter.setNativeInputChannel(nativeDup(mPtr));
}
WMS创建好了inputchannel之后返回到ViewRootImpl的setView方法的step3 创建mInputEventReceiver,来注册client端的InputChannel到主线程的looper。我们继续分析ViewRootImpl的setView
public void setView() {
// step3 创建mInputEventReceiver,
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
Looper.myLooper());
}
frameworks/base/core/java/android/view/ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
}
frameworks/base/core/java/android/view/InputEventReceiver.java
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
......
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
}
frameworks/base/core/jni/android_view_InputEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject inputChannelObj, jobject messageQueueObj) {
std::shared_ptr<InputChannel> inputChannel =
android_view_InputChannel_getInputChannel(env, inputChannelObj);
......
// 主线程的messageQueue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
......
// 创建NativeInputEventReceiver
sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
receiverWeak, inputChannel, messageQueue);
status_t status = receiver->initialize();
......
receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast<jlong>(receiver.get());
}
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
// client端的inputchannel的fd
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
// client端的inputChannel注册到主线程的looper
mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
// 事件回调
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
if (events & ALOOPER_EVENT_INPUT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? KEEP_CALLBACK : REMOVE_CALLBACK;
}
}
到这里可以看到client端的inputChannel注册到了主线程的looper 到此,两端的inputChannel就分别注册好了。总结一下:server端的注册到inputDispatcher的looper,client端的InputChannel是注册到主线程的looper。inputChannel实质是socketpair,fd注册到looper之后,当socket通道有数据时,唤醒epoll,执行回调函数处理事件数据.