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渲染原理
前面提到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
的描述是: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
// 比对 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
类的继承关系:
ANativeObjectBase
的定义如下:
template
class ANativeObjectBase : public NATIVE_TYPE, public REF
{…}
再看下Surface
的构造方法:
从构造函数的参数可以看到,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{
/**
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?”);
}
long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);
synchronized (mLock) {
if (mNativeObject != 0) {
nativeRelease(mNativeObject);
}
setNativeObjectLocked(newNativeObject);
}
}
}
在上面的relayoutWindow()
方法中
WMS
先通过winAnimator
的createSurfaceLocked()
方法得到了一个WindowSurfaceController
对象WindowSurfaceController
对象封装了SurfaceControl
对象WMS
调用WindowSurfaceController
对象的getSurface()
方法来对Surface
对象进行填充getSurface()
对象只是利用自身保存的mSurfaceControl
对象Surface
的copyFrom()
方法对Surface
对象进行填充处理copyFrom()
方法nativeGetFromSurfaceControl()
方法得到一个native
层的Surface
对象指针setNativeObjectLocked()
方法将指针保存到成员变量mNativeObject
中关键点又回到了native
层的nativeGetFromSurfaceControl()
方法,它的代码如下:
static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
jlong surfaceControlNativeObj) {
sp ctrl(reinterpret_cast
sp surface(ctrl->getSurface());
if (surface != NULL) {
surface->incStrong(&sRefBaseOwner);
}
return reinterpret_cast(surface.get());
}
nativeGetFromSurfaceControl()
方法是通过native
层的SurfaceControl
的getSurface()
方法来获取Surface
对象。我们再看下getSurface()
方法:
sp SurfaceControl::getSurface() const {
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
return generateSurfaceLocked();
}
return mSurfaceData;
}
sp SurfaceControl::generateSurfaceLocked() const {
mSurfaceData = new Surface(mGraphicBufferProducer, false);
return mSurfaceData;
}
在SurfaceControl
的getSurface()
方法中
mSurfaceData
指针为空时才会通过generateSurfaceLocked()
方法创建一个新的Surface
对象Surface
对象中很关键的IGraphicBufferProducer
在这里传入的是SurfaceControl
的成员变量mGraphicBufferProducer
mSurfaceData
指针从getSurface()
方法的逻辑中我们不难看出,SurfaceControl
对象和Surface
对象是关联在一起的,一对一的关系
更关键的是构造Surface
对象的核心参数竟然是SurfaceControl
中的成员变量。。。。。。。。
没办法,要先搞定SurfaceControl
的创建过程才可以
前面已经讲过,WMS
通过winAnimator.createSurfaceLocked()
方法创建了WindowSurfaceController
对象,WindowSurfaceController
对象初始化时就会创建SurfaceControl
,我们看下创建过程:
class WindowStateAnimator{
WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
…
// mSession 的类型就是前面提到的 Session 类,IWindowSession Binder服务类
mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, …);
…
return mSurfaceController;
}
}
class WindowSurfaceController{
public WindowSurfaceController(SurfaceSession s, …) {
…
final SurfaceControl.Builder b = win.makeSurface()
…
.setMetadata(windowType, ownerUid);
// 通过 Builder 模式创建的
mSurfaceControl = b.build();
}
}
class SurfaceControl{
public static class Builder {
…
public SurfaceControl build() {
…
// 调用私有构造方法
return new SurfaceControl(mSession, …);
}
…
}
private SurfaceControl(SurfaceSession session, …)
throws OutOfResourcesException, IllegalArgumentException {
…
mNativeObject = nativeCreate(session, …);
if (mNativeObject == 0) {
throw new OutOfResourcesException(
“Couldn’t allocate SurfaceControl native object”);
}
…
}
}
可以看到
SurfaceControl
对象的全程都携带着一个SurfaceSession
对象。SurfaceSession
对象在SurfaceControl
的构造方法中通过nativeCreate()
传递到了native层
,用来创建native层
的对象Java层
的Surface
对象一样,SurfaceControl
对象也会将native层
对象的指针保存到mNativeObject
中关键还是在nativeCreate()
方法,我们继续。。
nativeCreate()
方法如下:
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, …) {
ScopedUtfChars name(env, nameStr);
sp client(android_view_SurfaceSession_getClient(env, sessionObj));
…
sp surface;
status_t err = client->createSurfaceChecked(
String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
…
return reinterpret_cast(surface.get());
}
nativeCreate()
方法中又出现了一个新的类型SurfaceComposerClient
,而且native层
的SurfaceControl
对象就是通过它的createSurfaceChecked()
来创建的
耐心、耐心、耐心。。。。 崩溃的时候多说几次
上面方法中的SurfaceComposerClient
对象是通过android_view_SurfaceSession_getClient()
方法得到的,看JNI
的命名格式可以推算它和SurfaceSession
类也有关系,内容如下:
sp android_view_SurfaceSession_getClient(
JNIEnv* env, jobject surfaceSessionObj) {
return reinterpret_cast
env->GetLongField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
}
android_view_SurfaceSession_getClient()
方法中的参数surfaceSessionObj
是在Java层
调用nativeCreate()
方法时传递的参数,类型是SurfaceSession
。
这里实际上是将
SurfaceSession
对象中成员变量mNativeClient
的值取出来后,转换为SurfaceComposerClient
对象返回
这说明SurfaceComposerClient
对象和SurfaceSession
对象也是一起创建出来的,我们继续看下SurfaceSession
和SurfaceComposerClient
的创建过程
SurfaceControl.nativeCreate
到ComposerService
需要知道的一个重要前提:每个用户进程在
WMS
中都有且只有一个对应的Session
对象,前面已经介绍Session
是一个实现了IWindowSession
接口的Binder
服务类
Session
的成员变量mSurfaceSession
是在Session
对象初始化时创建的,那么Session
对象在什么时候创建的呢?
跟踪代码发现流程如下:
ViewRootImpl
初始化时会调用WindowManagerGlobal.getWindowSession()
方法WindowManagerGlobal.getWindowSession()
会调用WMS
的openSession()
方法openSession()
方法中便会在WMS
中创建一个新的Session
对象对于SurfaceSession
的初始化,是在Session
对象的windowAddedLocked()
方法中,那么windowAddedLocked()
方法又是在哪里调用的呢?
同样,我们跟踪下方法调用:
ViewRootImpl
的setView()
方法中会调用mWindowSession.addToDisplay(...)
方法mWindowSession.addToDisplay(...)
方法会调用WMS
的addWindow()
方法WMS
的addWindow()
方法会调用WindowState
的attach()
方法attach()
方法会调用Session
的windowAddedLocked()
方法这样就串起来了,现在我们可以继续学习SurfaceSession
的构造方法了:
/** Create a new connection with the surface flinger. */
public SurfaceSession() {
mNativeClient = nativeCreate();
}
很简洁,源码注释也很关键。我们看下SurfaceSession
的nativeCreate()
方法:
static jl
ong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
// 请注意此方法的调用
// 该方法会触发 onFirstRef() 的执行
client->incStrong((void*)nativeCreate);
return reinterpret_cast(client);
}
nativeCreate()
直接创建了一个SurfaceComposerClient
对象,也没有参数。不过SurfaceComposerClient
类是从RefBase
类派生出来的,我们看下它的构造函数和onFirstRef
函数:
构造方法很简单,只是将mStatus
设置为NO_INIT
。
重点是在onFirstRef()
方法中
ComposerService
的getComposerService()
方法来得到一个ISurfaceComposer
的指针createConnection()
方法创建一个ISurfaceComposerClient
对象mClient
指向这个ISurfaceComposerClient
对象咳咳咳,按照上面的调用流程我们还没有找到关于
IGraphicBufferProducer
的信息,现在又多出来了一个ISurfaceComposerClient
。。。
好吧好吧,梳理下这部分关系先
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() {