系列文章
目录
2.2 WindowManagerGlobal的addView
2.12 Java层openInputChannelPair
2.13 android_view_InputChannel_nativeOpenInputChannelPair
2.17 nativeRegisterInputChannel
2.18 android_view_InputChannel_getInputChannel
2.19 android_server_InputWindowHandle_getHandle
2.21 InputDispatcher::registerInputChannel
2.23 android_view_InputChannel_setDisposeCallback
1.简介
上一篇中,主要介绍了按键事件中inputdispatcher线程的分发流程,最后会通过sokcet对发送按键消息到应用端,那么这个socket对是什么时候创建的呢?是什么时候和IMS建立连接的呢?本文便主要解答一下这部分内容。
1.1 主要步骤
1.首先当Activity启动后,应用程序端会创建一个空的InputChannel对象。
2.然后应用程序端会通过binder调用到WMS服务,WMS服务会通过openInputChannel 方法会创建一对 InputChannel,一个给到IMS,一个会通过binder调用返回给应用端。
3.然后WMS会将其中一个socket注册到IMS服务中,IMS服务通过epoll机制来监听,是否有来自应用端发送的消息,当应用程序端通过sokcet发送消息时,IMS中的handleReceiveCallback回调函数会执行。
4.然后此时应用端到WMS的binder调用函数返回,返回给应用程序端一个socket,应用程序端会创建一个NativeInputEventReceiver对象,同时应用程序端也会通过epoll机制来监听,是否有来自IMS发送的消息,当存在IMS发送事件到应用程序端时,会调用NativeInputEventReceiver的handleEvent函数。
1.2 时序图

(图片可保存到本地放大观看)
2.源码分析
首先当Activity启动后,最终会调用到WindowManagerImpl.addView()函数,我们便从WindowManagerImpl.addView()函数进行分析。
2.1 WindowManagerImpl的addView
主要作用:
1.调用WindowManagerGlobal对象的addview对象。
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params)
{
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);//mGlobal就是WindowManagerGlobal对象
}
2.2 WindowManagerGlobal的addView
主要作用:
1.创建ViewRootImpl对象。
2.调用ViewRootImpl的setView函数,此函数会创建空的InputChannel对象,然后传给WMS,WMS会返回一个和IMS连接好的socket给应用程序端。
此时我们仍然在应用程序进程中。
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
//view代表添加哪个窗口,此时view是DecorView
//params窗口的参数
//display显示到那块屏幕上
//parentWindow父窗口是谁
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
int index = findViewLocked(view, false);//从mViews中查找此view是否已经存在
/*
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// The previous removeView() had not completed executing. Now it has.
}*/
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);//将此DecorView保存到mViews容器中
mRoots.add(root); //将此ViewRootImpl保存到容器中
mParams.add(wparams);//保存参数
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
2.3 ViewRootImpl
主要作用:
1.获取IWindowSession代理类,此类用于应用端和wms进行通信。
2.new W(this);W 继承自 IWindow.Stub,用于wms服务端向应用端通信。在调用本类的setView时会将此W对象传递给WMS。
//ViewRootImpl.Java
public ViewRootImpl(Context context, Display display) {
mContext = context;
mWindowSession = WindowManagerGlobal.getWindowSession();//获取IWindowSession代理类,此类用于应用和wms进行通信
mDisplay = display;//显示到那个display中
mDirty = new Rect();
mTempRect = new Rect();
mVisRect = new Rect();
mWinFrame = new Rect();
mWindow = new W(this);//w继承自class W extends IWindow.Stub,用于wms服务端向应用端通信
mFirst = true; // true代表此view第一次被添加
mChoreographer = Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
}
2.4 getWindowSession
主要作用:
1.获取和WMS通信用的Session对象。
//WindowManagerGlobal.java
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();//输入法
IWindowManager windowManager = getWindowManagerService();//获取wms的binder代理对象
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {//传入了客户端实现的WindowSessionCallback回调类,用于wms通信到应用程序
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
//aidl接口如下
IWindowSession openSession(in IWindowSessionCallback callback, in IInputMethodClient client,
in IInputContext inputContext);
2.5 WMS中的openSession
主要作用:
1.此时会走到WMS中,WMS中会创建一个session对象
//此时会调用到WMS中
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs
{
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
IInputContext inputContext)
{
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
Session session = new Session(this, callback, client, inputContext);
return session;//
}
}
2.6 Session
主要作用为:
1.此类内部会保存WindowManagerService对象和客户端实现的IWindowSessionCallback类对象
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient
{
public Session(WindowManagerService service, IWindowSessionCallback callback,
IInputMethodClient client, IInputContext inputContext) {
mService = service;//此时service是WindowManagerService对象
mCallback = callback;//callback是客户端实现的IWindowSessionCallback类对象,是一个binder对象
mClient = client;//此时是输入法的客户端
mUid = Binder.getCallingUid();
mPid = Binder.getCallingPid();
synchronized (mService.mWindowMap) {
if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
IBinder b = ServiceManager.getService(
Context.INPUT_METHOD_SERVICE);
mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);//获取输入法的binder代理对象
}
}
long ident = Binder.clearCallingIdentity();
try {
// Note: it is safe to call in to the input method manager
// here because we are not holding our lock.
if (mService.mInputMethodManager != null) {
mService.mInputMethodManager.addClient(client, inputContext,
mUid, mPid);//将此addClient添加到输入法中
} else {
client.setUsingInputMethod(false);
}
client.asBinder().linkToDeath(this, 0);
} catch (RemoteException e) {
// The caller has died, so we can just forget about this.
try {
if (mService.mInputMethodManager != null) {
mService.mInputMethodManager.removeClient(client);
}
} catch (RemoteException ee) {
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
2.7 class W
主要作用:
1.W 继承自 IWindow.Stub,用于wms服务端向应用端通信。在调用本类的setView时会将此W对象传递给WMS
static class W extends IWindow.Stub {
private final WeakReference<ViewRootImpl> mViewAncestor;
private final IWindowSession mWindowSession;
W(ViewRootImpl viewAncestor) {
mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
mWindowSession = viewAncestor.mWindowSession;//客户端保存IWindowSession session通信对象
}
}
2.8 setView
主要作用为:
1.应用端创建空的InputChannel对象。
2.应用端通过binder调用addToDisplay函数,此时会走到到wms服务中,在wms中会对mInputChannel赋值,并返回。返回的是一个已经和IMS连接的socket。
3.当应用端拿到socket后,会new WindowInputEventReceiver对象,此对象内部最终后调用应用端ui主线程的Looper::addFd函数,通过epoll机制监听此socket,当存在IMS发送事件到应用程序端时,会调用NativeInputEventReceiver的handleEvent函数。
//frmaework/base/core/java/android/view/ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
//view是view代表添加哪个窗口,此时view是DecorView
//params窗口的参数
//panelParentView,如果是子窗口,则子窗口存在父窗口,此时是普通窗口,则为null
synchronized (this) {
if (mView == null) {
mView = view;
mWindowAttri


2118

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



