以下分析基于Android S.
简述
在前面两篇文章中我们打通了应用进程和Input进程,这两者通过一对名为InputChannel实际是通过socket实现的通道来通信。然后我们又梳理了窗口信息是如何更新并传递给Input进程的。现在我们简单梳理一下一次触摸事件分发给窗口的过程。
事件要分发,首先是需要找到被分发的事件和对应的目标窗口。
以下分析基于Android S.
上文中我们知道Activity的Window被添加至WMS其实就是该Activity的ViewRootImpl中的W作为IWindow、存储该Activity窗口属性信息的LayoutParams以及InputChannel被传入WMS,然后生成WindowToken, 当然之后WindowToken自然是保存在DisplayContent.mTokenMap中,该map的key即对应Activity中的mToken(LocalActivityRecord)。
在Activity的Window被添加至WMS中,我们仅仅分析了一半,然后重点区分析了DisplayContent的构建,了解了其层次结构器的创建过程以及layer的个数和Window类型对应的layer。现在我们接着看WindowToken的创建,上文中留有一个疑问:
以下分析基于Android S.
在我们开始分析WMS是怎么管理不同应用的Window的时,有点一头雾水,不知如何下手。那么我们还是从单个Activity的Window被添加至WMS中来入手。
从上文中我们知道PhoneWindow是通过IWindowSession被添加的,在ViewRoontImpl中调用了addToDisplayAsUser:
1 | res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes, |
这里的mWindow是ViewRootImpl.W类的对象,用于WMS和该Window通信。
接上文,我们现在了解了binder驱动的加载过程,回过头继续分析App使用Binder通信的过程。
先回顾下App使用binder通信的大致过程:
之前我们分析到最后一步是:IPCThreadState#talkWithDriver
接上文,首先回顾一下IBinder相关接口的类图:
现在我们Client进程已经拿到Server端IDemoInterface中的IBinder对象,但是这个IBinder对象到底是哪个呢,Stub本身?还是Proxy亦或是Proxy中的mRemote?
还是看sayHello的调用过程先:
1 | override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) { |
Andorid Q
接着上文,当我们接收到来自App RenderThread线程渲染后的Surface之后,会在SurfaceFlinger收到下一次Vsync时做合成。
前面我们也稍微分析了一下,直接看handleMessageRefresh方法:
从上面trace上也可以看出收到Vsync后,sf首先调用handleMessageInvalidate检查时候需要进行合成。
如果需要就会调用方法handleMessageRefresh去做合成,最后将合成后的图像送入屏幕显示。
这里重点分析handleMessageRefresh.
Android Q
前面分析了Vsync信号的始末,其实还有很多可以细究的部分。比如硬件vsync是什么时候开始,什么时候结束?校准算法的原理等等。
接下来我们先看看SurfaceFlinger合成帧的部分。
Andorid Q
从这4个线程,可以将vsync分为4种不同的类型
这里我们着重看看SF EventThread.