Window Positioning
中的WindowManager
主要是用来控制Window
对象Window
对象是用来存放View
对象的容器,每个Window
对象都会关联Surface
对象WindowManager
监视Window
对象的生命周期、输入和焦点事件、屏幕方向、转换、动画、位置、变换、z顺序等然后将所有
Window
元数据发送给SurfaceFlinger
,SurfaceFlinger
利用这些元数据把自己管理的所有Surface
组合成layer
然后交给
Hardware Composer
做进一步处理HAL
层中的Hardware Composer(HWC)
会根据当前硬件来进一步进行缓冲区的组合,它的具体实现依赖于特定的显示设备官网关于
HWC
的数据流如下:
SurfaceFlinger
作为client
向HWC
提供一个完整的layer
列表,然后询问HWC
计划如何处理HWC
会将这些layer
标记为client合成
或者device合成
并告知SurfaceFlinger
SurfaceFlinger
将处理标记为client合成
的layer
,然后通过BufferQueue
传递给HWC
- 余下的
layer
由HWC
自行处理
网上一篇很有趣的渲染总结(文中有些错误,但瑕不掩瑜):Android渲染原理
VSYNC信号
前面提到Linux
使用Framebuffer
来用作显示输出。但是,如果在屏幕更新到一半时,用户进程更新了Framebuffer
中的数据,将导致屏幕上画面的上半部分是前一帧的画面,下半部分变成了新的画面。当然这种异常会在下次刷新时纠正过来,但是在用户感知上画面会出现闪烁感
- 针对这种情况,早期的解决方法是使用
双缓冲机制
,双缓冲就是提供两块Framebuffer
,一块用于显示,另一块用于数据更新,数据准备好后,通过ioctl
操作告诉显示设备切换用于显示的Framebuffer
,这样图像就能快速的显示出来了 - 但是双缓冲并没有完全解决问题,虽然双缓冲切换的速度很快,但是如果切换的时间点不对,在画面更新一半的时候进行切换,还是会出现单缓冲区遇到的闪烁问题
- 当然,可以在底层进行控制,当收到切换请求后内部并不马上执行,而是等到刷新完成后再切换,这样可以完全避免画面重叠的问题
- 但是,这样做会带来新的问题,如果
ioctl
操作完成后缓冲区没有切换,应用就不能确定何时可以再使用缓存区,只能通过ioctl
不停地查询缓冲区状态,直到切换完成。这种CPU
主动查询的方式很低效
为此Android
让底层固定地发送信号给用户进程,通知进程切换的时机,这样就避免了用户进程主动查询的操作。而这个信号就是VSYNC
信号
官方传送门:
VSYNC
官方描述如下:VSYNC
信号用来同步整个显示流程(Display Pipeline)
。显示流程
包括app
渲染、SurfaceFlinger
合成、HWC
(硬件渲染)组成
(这部分感觉原文更容易理解)VSYNC synchronizes the time apps wake up to start rendering, the time SurfaceFlinger wakes up to composite the screen, and the display refresh cycle.
VSYNC
信号应该由显示驱动产生,这样才能达到最佳效果。但是Android
为了能运行在不支持VSYNC
机制的设备上,也提供了用软件来模拟产生VSYNC
信号的手段
官网描述:通过
HWC
来产生VSYNC
信号,并通过接口回调将事件进行发送(主要是SurfaceFlinger
进行事件接收)
基础知识铺垫完成,我们先来看看Surface
Surface
官网对
Surface
的描述是:A surface is an interface for a producer to exchange buffers with a consumer.
上面描述的是一种生产者-消费者
的模式,而Surface
充当了中间衔接的角色。
以Activity
中UI
显示为例:
生产者
的任务就是把图形绘制在Surface
对象上比较出名的生产者就是
SurfaceView
组件了SurfaceFlinger
作为消费者
会把所有Surface
对应的图像层混合在一起最后
消费者
将其输出到FrameBuffer
中,这样在屏幕上就看到最后合成的图像了
下面我们从Java层
开始分析Surface
应用中Surface
的创建过程
应用开发中很少直接使用Surface
,因为每个Activity
中都已经创建好了各自的Surface
对象,通常只有一些特殊的应用才需要在Activity
之外再去创建Surface
,例如相机、视频播放应用。
不过,通常这些应用也是通过创建SurfaceView
来使用Surface
需要注意的是,在应用中不能直接去创建一个可用的Surface
对象(也可以说直接创建出的对象没什么实际用途),因为这样创建出的Surface
对象和SurfaceFlinger
之间没有任何关联。
该如何创见一个可用的Surface
对象呢?
我们看下Surface
类的定义:
public class Surface implements Parcelable {
long mNativeObject;
// 一个无参构造,空实现
public Surface() {
}
public Surface(SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
throw new IllegalArgumentException(“surfaceTexture must not be null”);
}
mIsSingleBuffered = surfaceTexture.isSingleBuffered();
synchronized (mLock) {
mName = surfaceTexture.toString();
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
}
}
}
Surface
类对外有两个构造方法:
一个是无参构造,实现也是空的
注释中说这个主要是给
readFromParcel()
反序列化用的那我们看下
readFromParcel()
方法
public void readFromParcel(Parcel source) {
if (source == null) {
throw new IllegalArgumentException(“source must not be null”);
}
synchronized (mLock) {
mName = source.readString();
mIsSingleBuffered = source.readInt() != 0;
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
}
}
另一个需要传递
SurfaceTexture
对象作为参数这就复杂了,还要准备一个
SurfaceTexture
对象
聪明的我们会发现,readFromParcel()
和new Surface(SurfaceTexture surfaceTexture)
都会执行一个setNativeObjectLocked()
方法,我们看下方法实现:
private void setNativeObjectLocked(long ptr) {
if (mNativeObject != ptr) {
…
mNativeObject = ptr;
…
}
}
setNativeObjectLocked()
方法很简单,只是更新了mNativeObject
变量的数值,重点就是参数了:
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
这两个setNativeObjectLocked()
方法的调用从参数的命名来看是针对不同数据来源的处理。
看来要看下native
的实现了,以nativeReadFromParcel()
为例来看下:
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
…
android::view::Surface surfaceShim;
// 解析 Parcel 数据,并填充到 native层 的 Surface对象 surfaceShim
surfaceShim.readFromParcel(parcel, /nameAlreadyRead/true);
// 将传入的指针转换为 native层 的 Surface对象 self
sp self(reinterpret_cast(nativeObject));
// 比对 surfaceShim 和 self 中的 Binder 对象 IGraphicBufferProducer
if (self != nullptr
&& (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
// 判断是同一个 IGraphicBufferProducer ,直接返回当前指针
return jlong(self.get());
}
sp sur;
if (surfaceShim.graphicBufferProducer != nullptr) {
// IGraphicBufferProducer 不同
// 且 surfaceShim 的 IGraphicBufferProducer 不为空
// 创建一个新的 Surface 对象 sur
sur = new Surface(surfaceShim.graphicBufferProducer, true);
sur->incStrong(&sRefBaseOwner);
}
…
// 将 sur 的指针返回给 Java 层
return jlong(sur.get());
}
到这里我们不难看出
Java层
的Surface
对象最重要的数据是mNativeObject
变量mNativeObject
是一个指针,指向的native
层的Surface
对象native
层在判断是否新建Surface
对象的逻辑依赖的是IGraphicBufferProducer
对象IGraphicBufferProducer
对象是一个Binder
引用对象
那么接下来我们重点就是这个IGraphicBufferProducer
了。
我们先看下native层
中Surface
类的继承关系:
- class Surface
- public ANativeObjectBase
ANativeObjectBase
的定义如下:
template <typename NATIVE_TYPE, typename TYPE, typename REF,
typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{…}
整理成继承关系图就是:
再看下Surface
的构造方法:
- Surface::Surface(const sp& bufferProducer, bool controlledByApp)
- mGraphicBufferProducer(bufferProducer),
mCrop(Rect::EMPTY_RECT),
mBufferAge(0),
…
mFrameEventHistory(std::make_unique()) {
… // 初始化各种成员变量
}
从构造函数的参数可以看到,native层
的Surface
将IGraphicBufferProducer
对象保存到了mGraphicBufferProducer
变量中。
暂时还是不清楚mGraphicBufferProducer
哪里来的,我们去WMS
中看看
WMS
中Surface
的创建过程
此处要从Activity
的onResume()
生命周期说起
onResume()
到WMS.relayoutWindow()
我们已经知道,当AMS
触发onResume()
生命周期时会调用到ActivityThread
类的handleResumeActivity()
方法,代码如下:
public void handleResumeActivity(…) {
…
// 此处会触发 onResume 声明周期回调
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
…
ViewManager wm = a.getWindowManager();
…// 省略很多 Window 处理逻辑
wm.addView(decor, l);
…
}
从方法中可以看到,执行完onResume()
后调用了ViewManager
的addView(decor, l)
方法
知识点:在
onResume
方法调用后才真正进行View
的添加
ViewManager
是一个接口类,真正的实现类是WindowManagerImpl
,addView()
方法实现也很简单:
public void addView(…) {
applyDefaultToken(params);
mGlobal.addView(…);
}
调用了mGlobal
的addView()
方法方法,mGlobal
的类型是WindowManagerGlobal
,代码如下:
public void addView(…) {
…
ViewRootImpl root;
synchronized (mLock) {
…
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
try {
root.setView(view, wparams, panelParentView);
}
…
}
}
WindowManagerGlobal
类的addView()
先是创建了一个新的ViewRootImpl
对象,然后调用了ViewRootImpl
对象的setView()
方法。
ViewRootImpl
类中setView()
调用流程如下:
class ViewRootImpl{
/**
- 这里也是直接 new 出来的对象 Surface
- 前面已经介绍过,这个对象需要和 native层进行绑定后才能正常使用
*/
public final Surface mSurface = new Surface();
ViewRootImpl(Context context, Display display){
…
// 此方法会创建 Session 对象
mWindowSession = WindowManagerGlobal.getWindowSession();
…
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
…
// 内部方法调用
requestLayout();
…
// 此方法会创建 SurfaceSession
res = mWindowSession.addToDisplay(…);
…
}
}
}
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
…
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
…
// 异步执行 mTraversalRunnable
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
…
}
}
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
…
performTraversals();
…
}
}
private void performTraversals() {
…
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
…
}
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
…
// 调用 mWindowSession 的 relayout 方法,并将 mSurface 对象传递过去
int relayoutResult = mWindowSession.relayout(…, mSurface);
…
return relayoutResult;
}
}
setView()
方法最后调用的是mWindowSession
的relayout()
方法。
mWindowSession
类型是IWindowSession
,是一个Binder
引用对象。真正的Binder
服务实现是com.android.server.wm.Session
类:
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
public Session(WindowManagerService service, …) {
mService = service;
…
}
public int relayout(…, Surface outSurface) {
…
int res = mService.relayoutWindow(…, outSurface);
…
return res;
}
}
终于走到了WMS
中,调用的是WMS
的relayoutWindow()
方法
WMS.relayoutWindow()
到SurfaceControl.nativeCreate()
和Surface
相关的调用关系如下:
class WindowManagerService{
public int relayoutWindow(…, Surface outSurface) {
…
result = createSurfaceControl(outSurface, …);
…
return result;
}
private int createSurfaceControl(Surface outSurface, …) {
…
WindowSurfaceController surfaceController;
…
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
…
if (surfaceController != null) {
surfaceController.getSurface(outSurface);
} else {
…
outSurface.release();
}
return result;
}
}
class WindowSurfaceController{
public WindowSurfaceController(…) {
…
final SurfaceControl.Builder b = win.makeSurface()
…
.setMetadata(windowType, ownerUid);
mSurfaceControl = b.build();
}
void getSurface(Surface outSurface) {
outSurface.copyFrom(mSurfaceControl);
}
}
class Surface{
public void copyFrom(SurfaceControl other) {
if (other == null) {
throw new IllegalArgumentException(“other must not be null”);
}
long surfaceControlPtr = other.mNativeObject;
if (surfaceControlPtr == 0) {
throw new NullPointerException(
“null SurfaceControl native object. Are you using a released SurfaceControl” />
ong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
// 请注意此方法的调用
// 该方法会触发 onFirstRef() 的执行
client->incStrong((void*)nativeCreate);
return reinterpret_cast(client);
}
nativeCreate()
直接创建了一个SurfaceComposerClient
对象,也没有参数。不过SurfaceComposerClient
类是从RefBase
类派生出来的,我们看下它的构造函数和onFirstRef
函数:
- SurfaceComposerClient::SurfaceComposerClient()
- mStatus(NO_INIT)
{
}
// onFirstRef() 是 RefBase 提供的回调接口
// 当首次调用 incStrong() 方法时便会执行此方法
void SurfaceComposerClient::onFirstRef() {
sp sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT) {
// 此处 rootProducer 应该为 null
auto rootProducer = mParent.promote();
sp conn;
// 所以在此处执行的是 sf->createConnection() 方法
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
构造方法很简单,只是将mStatus
设置为NO_INIT
。
重点是在onFirstRef()
方法中
- 先调用了
ComposerService
的getComposerService()
方法来得到一个ISurfaceComposer
的指针 - 然后调用它的
createConnection()
方法创建一个ISurfaceComposerClient
对象 - 然后将
mClient
指向这个ISurfaceComposerClient
对象
咳咳咳,按照上面的调用流程我们还没有找到关于
IGraphicBufferProducer
的信息,现在又多出来了一个ISurfaceComposerClient
。。。
好吧好吧,梳理下这部分关系先
WMS
中Surface
关系总结
上面介绍的WMS
中涉及和Surface
有关的类关系如下:
看上去就挺复杂的:
SurfaceControl
和Surface
是成对创建的,考虑到绘制等需求,它们的数量会比较多Session
、SurfaceSession
和SurfaceComposerClient
对象是和连接WMS
的用户进程的数量相同SurfaceComposerClient
的作用是创建Surface
SurfaceControl
通过SurfaceComposerClient
来获取Surface
SurfaceComposerClient
是ComposerService
的具体实现类
ComposerService
再到SurfaceFlinger
ComposerService
是一个单例模式的普通类,定义如下:
class ComposerService : public Singleton
{
sp mComposerService;
spIBinder::DeathRecipient mDeathObserver;
Mutex mLock;
ComposerService();
void connectLocked();
void composerServiceDied();
friend class Singleton;
public:
static sp getComposerService();
};
前面的onFirstRef()
方法中调用了ComposerService
类的静态方法getComposerService()
,我们看下它的实现:
/static/ sp ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
…
}
return instance.mComposerService;
}
getComposerService()
通过调用父类Singleton
的getInstance()
方法来取得实例对象,然后调用ComposerService
的connectLocked()
方法:
void ComposerService::connectLocked() {
();
void composerServiceDied();
friend class Singleton;
public:
static sp getComposerService();
};
前面的onFirstRef()
方法中调用了ComposerService
类的静态方法getComposerService()
,我们看下它的实现:
/static/ sp ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
…
}
return instance.mComposerService;
}
getComposerService()
通过调用父类Singleton
的getInstance()
方法来取得实例对象,然后调用ComposerService
的connectLocked()
方法:
void ComposerService::connectLocked() {