Input属于SystemServer进程,要想把事件分发给应用,需要和应用跨进程通信,这里看下InputChannel的建立过程。
- 在向Window添加View的过程中会创建客户端的InputChannel对象,并在调用addToDisplayAsUser时,将inputChannel传给WindowManagerService。可以看到这里还创建了很多InputStage,InputStage用于应用处理事件,这个后面再分析。
ini
// frameworks/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;
...
InputChannel inputChannel = null;
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
// 创建InputChannel
inputChannel = new InputChannel();
}
try {
...
// 将InputChannel传给WindowManagerService
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibleTypes(), inputChannel, mTempInsets,
mTempControls, attachedFrame, compatScale);
...
} catch (RemoteException | RuntimeException e) {
...
}
// 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;
}
}
java
// frameworks/base/services/core/java/com/android/server/wm/Session.java
@Override
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, int userId, @InsetsType int requestedVisibleTypes,
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
float[] outSizeCompatScale) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
requestedVisibleTypes, outInputChannel, outInsetsState, outActiveControls,
outAttachedFrame, outSizeCompatScale);
}
- 如果没有INPUT_FEATURE_NO_INPUT_CHANNEL就创建InputChannel。
java
// frameworks/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, @InsetsType int requestedVisibleTypes,
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
float[] outSizeCompatScale) {
...
final boolean openInputChannels = (outInputChannel != null
&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
win.openInputChannel(outInputChannel);
}
...
}
- 在系统启动过程中,会将inputManagerService传给WindowManagerService。这里调用IMS来创建InputChannel,并将channel的client端传给应用。
ini
// frameworks/base/services/core/java/com/android/server/wm/WindowState.java
void openInputChannel(@NonNull InputChannel outInputChannel) {
if (mInputChannel != null) {
throw new IllegalStateException("Window already has an input channel.");
}
String name = getName();
mInputChannel = mWmService.mInputManager.createInputChannel(name);
mInputChannelToken = mInputChannel.getToken();
mInputWindowHandle.setToken(mInputChannelToken);
mWmService.mInputToWindowMap.put(mInputChannelToken, this);
mInputChannel.copyTo(outInputChannel);
}
- 调用到Native创建InputChannel。
ruby
// frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public InputChannel createInputChannel(String name) {
return mNative.createInputChannel(name);
}
- 调用到InputDispacher
c
// frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jobject nativeCreateInputChannel(JNIEnv* env, jobject nativeImplObj, jstring nameObj) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
ScopedUtfChars nameChars(env, nameObj);
std::string name = nameChars.c_str();
base::Result<std::unique_ptr<InputChannel>> inputChannel = im->createInputChannel(name);
if (!inputChannel.ok()) {
std::string message = inputChannel.error().message();
message += StringPrintf(" Status=%d", static_cast<int>(inputChannel.error().code()));
jniThrowRuntimeException(env, message.c_str());
return nullptr;
}
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(
const std::string& name) {
ATRACE_CALL();
return mInputManager->getDispatcher().createInputChannel(name);
}
- 创建InputChannel,并把server端封装到Connection中,Connection主要用来管理与InputChannel相关的状态。最后把clientChannel返回给应用,用于给Input发送消息。
c
// frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
if (DEBUG_CHANNEL_CREATION) {
ALOGD("channel '%s' ~ createInputChannel", name.c_str());
}
std::unique_ptr<InputChannel> serverChannel;
std::unique_ptr<InputChannel> clientChannel;
// 创建Channel
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
if (result) {
return base::Error(result) << "Failed to open input channel pair with name " << name;
}
{ // acquire lock
std::scoped_lock _l(mLock);
const sp<IBinder>& token = serverChannel->getConnectionToken();
const int fd = serverChannel->getFd();
std::shared_ptr<Connection> connection =
std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false,
mIdGenerator);
// 将服务端通道的`IBinder token`和对应的`Connection`对象存入映射表,用于后续事件分发。
auto [_, inserted] = mConnectionsByToken.try_emplace(token, connection);
if (!inserted) {
ALOGE("Created a new connection, but the token %p is already known", token.get());
}
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
// 将服务端通道的Socket文件描述符注册到Looper,监听输入事件(ALOOPER_EVENT_INPUT)。当应用有事件可读时,触发回调handleReceiveCallback、。
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
nullptr);
} // release lock
// Wake the looper because some connections have changed.
mLooper->wake();
return clientChannel;
}
- 可以看到InputChannel是用Socket实现的。
c
// frameworks/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];
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;
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 = sp<BBinder>::make();
std::string serverChannelName = name + " (server)";
android::base::unique_fd serverFd(sockets[0]);
outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);
std::string clientChannelName = name + " (client)";
android::base::unique_fd clientFd(sockets[1]);
outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
return OK;
}