基于Android 7.0源码分析
通常,Android应用启动时,在Activity的生命周期onResume()
执行结束后,会将Activity的窗口注册到WindowManagerService
,由WindowManagerService
创建好InputChannel
后,通过Binder IPC回传给应用。下面我们从WindowManagerGlobal
的addView()
开始分析。
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
......
synchronized (mLock) {
......
// 创建ViewRootImpl对象
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
// 调用ViewRootImpl的setView
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
}
- ViewRootImpl 顶层View层级,实现了View和WindowManager之间的交互协议
下面看ViewRootImpl
的SetView()
的实现
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
......
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
// 创建空的InputChannel,内部状态在Binder IPC addToDisplay返回时创建(细节请查看IWindowSession.java)
mInputChannel = new InputChannel();
}
......
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
// 窗口注册到WindowManagerService
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
} catch (RemoteException e) {
mAdded = false;
mView = null;
mAttachInfo.mRootView = null;
mInputChannel = null;
mFallbackEventHandler.setView(null);
unscheduleTraversals();
setAccessibilityFocus(null, null);
throw new RuntimeException("Adding window failed", e);
} finally {
if (restore) {
attrs.restore();
}
}
......
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
// 创建WindowInputEventReceiver对象,负责接收输入事件
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
......
// Set up the input pipeline.
// 创建InputState链处理输入事件,采用职责链模式
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;
mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;
}
}
}
mWindowSession
是一个IWindowSession.Stub.Proxy
类型的代理对象,它是在ViewRootImpl
的构造方法中创建的,对应的服务对象是Session
对象,下面看Session
的addToDisplay()
的实现。
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
Rect outOutsets, InputChannel outInputChannel) {
// mService是WindowManagerService对象
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
- Session 表示一个激活的客户端会话,通常,WindowManagerService为每个与其交互的客户进程创建一个Session
下面看WindowManagerService
的addWindow()
的实现
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
......
synchronized(mWindowMap) {
......
// 创建WindowState用于描述一个窗口
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
......
if (openInputChannels) {
// 创建InputChannel, 注册InputChannel到InputManager
win.openInputChannel(outInputChannel);
}
......
}
......
}
下面看WindowState
的openInputChannel()
的实现
void openInputChannel(InputChannel outInputChannel) {
if (mInputChannel != null) {
throw new IllegalStateException("Window already has an input channel.");
}
// 输入通道名字
String name = makeInputChannelName();
// 创建一对输入通道
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
// 用于服务端发布输入事件
mInputChannel = inputChannels[0];
// 用于客户端消耗输入事件
mClientChannel = inputChannels[1];
mInputWindowHandle.inputChannel = inputChannels[0];
if (outInputChannel != null) {
// mClientChannel的内部状态设置到outInputChannel
// 最终outInputChannel通过Binder IPC返回给客户端
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);
}
// 向InputManagerService注册输入通道(观察者模式)
// mInputWindowHandle为InputWindowHandle对象,用于Native层的Input Dispathcer获取窗口状态
mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
}
下面首先看输入通道的创建openInputChannelPair()
, 它是一个Native方法,对应的实现在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);
sp serverChannel;
sp clientChannel;
// 创建socket pair
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
if (result) {
String8 message;
message.appendFormat("Could not open input channel pair. status=%d", result);
jniThrowRuntimeException(env, message.string());
return NULL;
}
// 创建Java层的InputChannel数组对象
jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
if (env->ExceptionCheck()) {
return NULL;
}
// 创建Java层服务端InputChannel对象,NativeInputChannel相当于中介者
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
new NativeInputChannel(serverChannel));
if (env->ExceptionCheck()) {
return NULL;
}
// 创建Java层客户端InputChannel对象
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
new NativeInputChannel(clientChannel));
if (env->ExceptionCheck()) {
return NULL;
}
// 设置Java层InputChannel数组中的对象
env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
return channelPair;
}
下面看openInputChannelPair()
的实现
status_t InputChannel::openInputChannelPair(const String8& name,
sp& outServerChannel, sp& 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=%d",
name.string(), errno);
outServerChannel.clear();
outClientChannel.clear();
return result;
}
// 设置socket发送、接收缓冲区
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));
String8 serverChannelName = name;
serverChannelName.append(" (server)");
// 创建服务端InputChannel
outServerChannel = new InputChannel(serverChannelName, sockets[0]);
String8 clientChannelName = name;
clientChannelName.append(" (client)");
// 创建客户端InputChannel
outClientChannel = new InputChannel(clientChannelName, sockets[1]);
return OK;
}
至此,InputChannel
的创建已经完成,下面看InputChannel
的注册,下面从InputManagerService
的registerInputChannel
开始分析
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
NativeInputManager* im = reinterpret_cast(ptr);
// 获取inputChannelObj关联的Native层的InputChannel
sp inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
if (inputChannel == NULL) {
throwInputChannelNotInitialized(env);
return;
}
// 获取inputWindowHandleObj关联的Native层InputWindowHandle
sp inputWindowHandle =
android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
// 注册输入通道
status_t status = im->registerInputChannel(
env, inputChannel, inputWindowHandle, monitor);
......
}
NativeInputManager
的registerInputChannel()
最终调用InputDispatcher
的registerInputChannel()
.
status_t InputDispatcher::registerInputChannel(const sp& inputChannel,
const sp& inputWindowHandle, bool monitor) {
......
{ // acquire lock
AutoMutex _l(mLock);
// 检查是否已经注册过
if (getConnectionIndexLocked(inputChannel) >= 0) {
ALOGW("Attempted to register already registered input channel '%s'",
inputChannel->getName().string());
return BAD_VALUE;
}
// 创建Connection,用于管理关联的InputChannel的事件分发状态
sp connection = new Connection(inputChannel, inputWindowHandle, monitor);
int fd = inputChannel->getFd();
// 添加到mConnectionsByFd容器中
mConnectionsByFd.add(fd, connection);
if (monitor) {
mMonitoringChannels.push(inputChannel);
}
// 监听fd上的I/O操作,当有I/O操作时,回调handleReceiveCallback处理
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
} // release lock
// Wake the looper because some connections have changed.
// 唤醒InputDispatcherThread
mLooper->wake();
return OK;
}
至此,系统进程的工作已经完成,下面分析应用处理Biner IPC返回的InputChannel
, 回到ViewRootImpl
的setView()
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
......
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
// 窗口注册到WindowManagerService
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
} catch (RemoteException e) {
mAdded = false;
mView = null;
mAttachInfo.mRootView = null;
mInputChannel = null;
mFallbackEventHandler.setView(null);
unscheduleTraversals();
setAccessibilityFocus(null, null);
throw new RuntimeException("Adding window failed", e);
} finally {
if (restore) {
attrs.restore();
}
}
......
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
// 创建WindowInputEventReceiver对象,负责接收输入事件
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
......
}
我们知道,ViewRootImpl
创建的mInputChannel
是个空的InputChannel
,其内部状态在addToDisplay()
返回时才构造完成(原理是跨进程传递文件描述符)。 InputChannel
构造完成后,创建WindowInputEventReceiver
(继承自InputEventReceiver
)用于接收输入事件。下面直接看InputEventReceiver
的构造方法。
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");
}
// 关联的InputChannel
mInputChannel = inputChannel;
// UI线程的消息队列
mMessageQueue = looper.getQueue();
// 调用nativeInit
mReceiverPtr = nativeInit(new WeakReference(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
下面看nativeInit()
的实现
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject inputChannelObj, jobject messageQueueObj) {
// 获取Native层的InputChannel
sp inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
if (inputChannel == NULL) {
jniThrowRuntimeException(env, "InputChannel is not initialized.");
return 0;
}
// 获取Native层的NativeMessageQueue
sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// 创建NativeInputEventReceiver对象
sp receiver = new NativeInputEventReceiver(env,
receiverWeak, inputChannel, messageQueue);
// 监听InputChannel
status_t status = receiver->initialize();
......
}
下面看initialize()
的实现
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
// 监听套接字fd,当收到输入事件时,回调NativeInputEventReceiver的handleEvent
mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}