surface概述
每一个在C++层实现的应用程序窗口都需要有一个绘图表面,然后才可以将自己的UI表现出来。这个绘图表面是需要由应用程序进程请求SurfaceFlinger服务来创建的,在SurfaceFlinger服务内部使用一个Layer对象来描述,同时,SurfaceFlinger服务会返回一个实现了ISurface接口的Binder本地对象给应用程序进程,于是,应用程序进程就可以获得一个实现了ISurface接口的Binder代理对象。有了这个实现了ISurface接口的Binder代理对象之后,在C++层实现的应用程序窗口就可以请求SurfaceFlinger服务分配图形缓冲区以及渲染已经填充好UI数据的图形缓冲区了。
java层的surface:
public class Surface implements Parcelable{
...
private final Canvas mCanvas = new CompatibleCanvas();
//两个构造函数
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));
}
}
}
由于在Java层实现的Android应用程序窗口还要接受WindowManagerService服务管理,因此,它的绘图表面的创建流程就会比在C++层实现的应用程序窗口复杂一些。具体来说,就是在在Java层实现的Android应用程序窗口的绘图表面是通过两个Surface对象来描述,一个是在应用程序进程这一侧创建的,另一个是在WindowManagerService服务这一侧创建的,它们对应于SurfaceFlinger服务这一侧的同一个Layer对象
在应用程序进程这一侧,每一个应用程序窗口,即每一个Activity组件,都有一个关联的Surface对象,这个Surface对象是保
在WindowManagerService服务这一侧,每一个应用程序窗口,即每一个Activity组件,都有一个对应的WindowState对象,这个WindowState对象的成员变量mSurface同样是指向了一个Surface对象,在WindowManagerService服务这一侧,每一个Java层的Surface对都对应有一个C++层的SurfaceControl对象。
就是位于应用程序进程这一侧的Surface对象负责绘制应用程序窗口的UI,即往应用程序窗口的图形缓冲区填充UI数据,而位于WindowManagerService服务这一侧的Surface对象负责设置应用程序窗口的属性,例如位置、大小等属性。
创建surface对象的步骤:
- 应用程序进程请求WindowManagerService服务为一个应用程序窗口创建一个Surface对象;
- WindowManagerService服务请求SurfaceFlinger服务创建一个Layer对象,并且获得一个ISurface接口;
- WindowManagerService服务将获得的ISurface接口保存在其内部的一个Surface对象中,并且将该ISurface接口返回给应用程序进程;
- 应用程序进程得到WindowManagerService服务返回的ISurface接口之后,再将其封装成其内部的另外一个Surface对象中。
应用开发中很少直接使用Surface,因为每个activity中已经建好了各自的Surface对象。
在在一个关联的ViewRootImpl对象的成员变量mSurface中的。在ViewRootImp中有:
public final Surface mSurface = new Surface();
ViewRootImpl中performTraversals(其他文章讲)会调用relayoutWindow,而:
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
...
int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
mPendingMergedConfiguration, mSurface);
...
}
mWindowSession的声明是:
final IWindowSession mWindowSession;
初始化是:
mWindowSession = WindowManagerGlobal.getWindowSession();
在WindowManagerGlobal:
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
在
WMS中,
@Override
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 session = new Session(this, callback, client, inputContext);
return session;
}
回到前面,调用完relayout后surface就被赋值了.而binder调用都是parcel传输过来的数据,Surface是可以Parcel的.
Surface.java中:
public void readFromParcel(Parcel source) {
if (source == null) {
throw new IllegalArgumentException("source must not be null");
}
synchronized (mLock) {
// nativeReadFromParcel() will either return mNativeObject, or
// create a new native Surface and return it after reducing
// the reference count on mNativeObject. Either way, it is
// not necessary to call nativeRelease() here.
// NOTE: This must be kept synchronized with the native parceling code
// in frameworks/native/libs/Surface.cpp
mName = source.readString();
mIsSingleBuffered = source.readInt() != 0;
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
}
}
nativeReadFromParcel从Parcel对象中读取一个Binder对象, 并作为参数创建了一个本地的Surface对象, 最后这个本地的surface对象的指针传递回java层,保存在了mNativeObject中:
Surface.java中:
private void setNativeObjectLocked(long ptr) {
if (mNativeObject != ptr) {
if (mNativeObject == 0 && ptr != 0) {
mCloseGuard.open("release");
} else if (mNativeObject != 0 && ptr == 0) {
mCloseGuard.close();
}
mNativeObject = ptr;
mGenerationId += 1;
if (mHwuiContext != null) {
mHwuiContext.updateSurface();
}
}
}
因而, java层的Surface对象是从WMS中的一个binder中读出来从而联系在一起的.
下面去
WMS中看一下这个binder是哪里来的:
在ViewRootImpl调用mWindowSession.relayout来生成Surface, 然后WMS中的Session.java中:
int res = mService.relayoutWindow(this, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
outStableInsets, outsets, outBackdropFrame, cutout,
mergedConfiguration, outSurface);
会调用到WMS中的relayoutWindow:
public int relayoutWindow(Session session, IWindow client, int seq, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
Surface outSurface) {
...
result = createSurfaceControl(outSurface, result, win, winAnimator);
...
}
private int createSurfaceControl(Surface outSurface, int result, WindowState win,
WindowStateAnimator winAnimator) {
...
WindowSurfaceController surfaceController;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
}
...
surfaceController.getSurface(outSurface);
...
return result;
}
所以, relayoutWindow方法通过winAnimator创建了surfaceController, 并最终调用了Surface的copyFrom函数:
WindowSurfaceController.java中:
void getSurface(Surface outSurface) {
outSurface.copyFrom(mSurfaceControl);
}
Surface.java中:
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);
}
}
copyFrom调用nativeGetFromSurfaceControl得到newNativeObject,并通过setNativeObjectLocked将其保存在mNativeObject中.
java层的SurfaceControl 对象是通过winAnimatorde createSurfaceLocked函数创建的.
WindowStateAnimator.java:
WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
attrs.getTitle().toString(), width, height, format, flags, this,
windowType, ownerUid);
}
public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
mAnimator = animator;
mSurfaceW = w;
mSurfaceH = h;
title = name;
mService = animator.mService;
final WindowState win = animator.mWin;
mWindowType = windowType;
mWindowSession = win.mSession;
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
final SurfaceControl.Builder b = win.makeSurface()
.setParent(win.getSurfaceControl())
.setName(name)
.setSize(w, h)
.setFormat(format)
.setFlags(flags)
.setMetadata(windowType, ownerUid);
mSurfaceControl = b.build();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
b.build调用:
public SurfaceControl build() {
if (mWidth <= 0 || mHeight <= 0) {
throw new IllegalArgumentException(
"width and height must be set");
}
return new SurfaceControl(mSession, mName, mWidth, mHeight, mFormat,
mFlags, mParent, mWindowType, mOwnerUid);
}
而在SurfaceControl的构造函数中:
mNativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
SurfaceControl的nativeCreate实际上是将SurfaceSession中的成员变量mNativeClient取出来返回的.
每个用户进程在
WMS中有一个Session对象和他对应. Session的成员对象mSurfaceSession是在Session初始化的时候创建的.
SurfaceSession创建也是native的.SurfaceSession和SurfaceComposerClient对应,SurfaceComposerClient的作用是创建Surface.SurfaceComposerClient是ComposerService的客户端.
SurfaceComposerClient的createSurface()函数获取SufaceControl对象, 传递的参数是handle和gdp,他们都是binder对象. 他们的值会在SurfaceFlinger中设置.其中gdp就是重要的图像缓存区对象.handle是利用Binder对象的全局唯一性来为Surface生成一个唯一标识符.
管理图像缓冲区
native的Surface对象最重要的对象是IGraphicBufferProducer, 它对应的Binder实体就是SurfaceFlinger的MOnitoredProducer对象.这个对象和BufferQueueCore有关联,可以管理最多64块缓冲区.
BufferQueueProducer
BufferQueueConsumer
Surface是图像的生产者
在看创建Surface的时候, 有过layer的onFirstRef()函数中, 调用了BufferQueue的createBufferQueue(), 这个函数中创建了三个对象, BufferQueueCore, BufferQueueProducer, BufferQueueConsumer. 其中, BufferQueueCore是核心, 把BufferQueueProducer和BufferQueueConsumer连在了一起.
在BufferQueueCore定义了一个64项的数组mSlots.每项缓冲区的类型是:
struct BufferSlot {
...
sp<GraphicBuffer> mGraphicBuffer;
BufferState mBufferState;
...
}
mGraphicBuffer是指向图形缓冲区GraphicBuffer的指针
mBufferState表示图像缓冲区的状态
const char* BufferState::string() const {
if (isShared()) {
return "SHARED";
}
if (isFree()) {
return "FREE";
}
if (isAcquired()) {
return "ACQUIRED";
}
if (isDequeued()) {
return "DEQUEUED";
}
if (isQueued()) {
return "QUEUED";
}
return "UNKNOWN";
}
dequeueBuffer()函数用来向BufferQueueCore申请一个空闲的slot,这个slot上可能已经有缓冲区,也可能没有.
如果没有,那么分配一个新的缓冲区;得到空闲slot后, 还需要调用requestBuffer函数来取得一块缓冲区;得到缓冲区后不需要了, 可以使用cancelBuffer来释放这个slot.
调用dequeueBuffer函数后,缓存区的拥有者是"生产者", 缓冲区处于DEQUEUE状态;一旦完成向缓冲区的复制数据, 通过调用queueBuffer函数将把缓冲区的控制权交还给BufferQueueCore,这时缓冲区将处于QUEUED状态.
取走数据需要调用函数acquireBuffer(), 将缓冲区的状态变为ACQUIRED,使用完数据后, 调用releaseBuffer()函数将缓冲区还给BufferQueueCore, 这时缓冲区的状态变成了FREE.