之前在分析Activity的时候,我们分析过Surface创建。这个系列的博客是讲述显示系统,这里再系统的分析下Surface创建过程。
之前我们分析在Activity在调用attach方法时,建立ViewRootImpl,以及创建其Surface过程,还有在WMS中创建Surface的过程。
这篇博客我们通过另外一个方式分析,但是其实质是一样的。
应用开发中很少直接使用Surface,因为每个Activity中已经创建好了各自的Surface对象(就是之前博客分析的在ViewRootImpl通过WMS创建的),通常只有一些特殊应用才需要在Activity之外创建Surface,例如照相机、视频播放应用。通常这些应用也是通过创建SurfaceView来使用Surface。在应用中不直接创建一个可用的Surface对象,或者说直接创建出来的Surface对象也没用,因为这样的Surface不能和SurfaceFlinger之间有关联。
下面我们就来看下SurfaceView是如何创建Surface的,在SurfaceView有两个Surface一个mSurface表示正在用的,另一个mNewSurface代表我们要切换的。
final Surface mSurface = new Surface(); // Current surface in use
final Surface mNewSurface = new Surface(); // New surface we are switching to
至于Surface的构造函数没什么代码,我们就不看了。
我们再来看SurfaceView的updateWindow函数,也是调用了WindowSession的relayout函数,和之前Activity创建Surface的流程一样,这里获取到mNewSurface,再把mNewSurface的数据复制到mSurface中。
protected void updateWindow(boolean force, boolean redrawNeeded) {
......
relayoutResult = mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
visible ? VISIBLE : GONE,
WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
mWinFrame, mOverscanInsets, mContentInsets,
mVisibleInsets, mStableInsets, mOutsets, mConfiguration,
mNewSurface);
......
mSurface.transferFrom(mNewSurface);
......
}
mSession对象是IWindowSession,它是WMS中Session的代理对象。下面这是IWindowSession.aidl文件中relayout函数的定义,我们可以看到outSurface的参数前面有一个out代表这是一个返回参数,从WMS获取这个对象的。而返回数据都是通过Parcel来传递的。那下面我们来看看Surface的readFromParcel函数。
int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility,
int flags, out Rect outFrame, out Rect outOverscanInsets,
out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
out Rect outOutsets, out Configuration outConfig, out Surface outSurface);
我们来看下Surface的readFromParcel函数,前面是参数检查,后面先是调用了nativeReadFromParcel函数来重新创建一个native层的Surface,然后调用setNativeObjectLocked来保存这个native层的Surface到mNativeObject对象
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.
mName = source.readString();
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
}
}
我们来看JNI层的nativeReadFromParcel函数,这个函数在android_view_Surface.cpp中,会将Parcel对象中读取一个Binder对象,并且用它创建一个c层的Surface,并且返回。这里我们还不清楚这个Binder是什么。
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);//将数据解析成parcel
if (parcel == NULL) {
doThrowNPE(env);
return 0;
}
sp self(reinterpret_cast(nativeObject));
sp binder(parcel->readStrongBinder());
// update the Surface only if the underlying IGraphicBufferProducer
// has changed.
if (self != NULL //和原来的相同
&& (IInterface::asBinder(self->getIGraphicBufferProducer()) == binder)) {
// same IGraphicBufferProducer, return ourselves
return jlong(self.get());
}
sp sur;
sp gbp(interface_cast(binder));
if (gbp != NULL) {
// we have a new IGraphicBufferProducer, create a new Surface for it
sur = new Surface(gbp, true);//创建一个Surface
// and keep a reference before passing to java
sur->incStrong(&sRefBaseOwner);
}
if (self != NULL) {
// and loose the java reference to ourselves
self->decStrong(&sRefBaseOwner);
}
return jlong(sur.get());
}
我们来看Surface,我们把binder对象保存在mGraphicBufferProducer中了。
Surface::Surface(
const sp& bufferProducer,
bool controlledByApp)
: mGraphicBufferProducer(bufferProducer),
mGenerationNumber(0)
用户进程中调用Session类的relayout接口来获取WMS创建的Surface。而Session类的relayout接口实际上后面调用了WMS的relayout的relayoutWindow方法。
我们来看下WMS的relayoutWindow函数,显示调用了winAnimator的createSurfaceLocked方法得到一个SurfaceControl对象,并使用它作为参数调整Surface类的copyFrom方法。
public int relayoutWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, int flags,
Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Configuration outConfig,
Surface outSurface) {
......
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
if (surfaceControl != null) {
outSurface.copyFrom(surfaceControl);
}
......
我们先来看Surface的copyFrom方法,这个方法其实很简单只是把SurfaceControl的native层的SurfaceControl的Surface复制到Surface的mNativeObject
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(
"SurfaceControl native object is null. Are you using a released SurfaceControl?");
}
long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
synchronized (mLock) {
if (mNativeObject != 0) {
nativeRelease(mNativeObject);
}
setNativeObjectLocked(newNativeObject);
}
}
nativeCreateFromSurfaceControl方法是把native层的SurfaceControl的surface传出去。
static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
jlong surfaceControlNativeObj) {
/*
* This is used by the WindowManagerService just after constructing
* a Surface and is necessary for returning the Surface reference to
* the caller. At this point, we should only have a SurfaceControl.
*/
sp ctrl(reinterpret_cast(surfaceControlNativeObj));
sp surface(ctrl->getSurface());//获取Surface
if (surface != NULL) {
surface->incStrong(&sRefBaseOwner);
}
return reinterpret_cast(surface.get());//这个get方法是强指针的方法,获取其指针而已
}
再来看看SurfaceControl的getSurface方法。
sp SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
// This surface is always consumed by SurfaceFlinger, so the
// producerControlledByApp value doesn't matter; using false.
mSurfaceData = new Surface(mGraphicBufferProducer, false);
}
return mSurfaceData;
}
下面我们再来看看SurfaceControl的创建,下面SurfaceTrace是SurfaceControl的一个子类。
SurfaceControl createSurfaceLocked() {
......
mSurfaceControl = new SurfaceTrace(
mSession.mSurfaceSession,
attrs.getTitle().toString(),
width, height, format, flags);
......
我们先看下SurfaceTrace的构造函数,先调用了父类的构造函数
public SurfaceTrace(SurfaceSession s,
String name, int w, int h, int format, int flags)
throws OutOfResourcesException {
super(s, name, w, h, format, flags);
mName = name != null ? name : "Not named";
mSize.set(w, h);
synchronized (sSurfaces) {
sSurfaces.add(0, this);
}
}
我们再来看SurfaceControl的构造函数,就是调用了nativeCreate来新建一个mNativeObject对象。前面我们看过通过这个对象就可以获取native层的Surface。
public SurfaceControl(SurfaceSession session,
String name, int w, int h, int format, int flags)
throws OutOfResourcesException {
if (session == null) {
throw new IllegalArgumentException("session must not be null");
}
if (name == null) {
throw new IllegalArgumentException("name must not be null");
}
if ((flags & SurfaceControl.HIDDEN) == 0) {
Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
+ "to ensure that they are not made visible prematurely before "
+ "all of the surface's properties have been configured. "
+ "Set the other properties and make the surface visible within "
+ "a transaction. New surface name: " + name,
new Throwable());
}
mName = name;
mNativeObject = nativeCreate(session, name, w, h, format, flags);
if (mNativeObject == 0) {
throw new OutOfResourcesException(
"Couldn't allocate SurfaceControl native object");
}
mCloseGuard.open("release");
}
我们来看SurfaceControl的nativeCreate的JNI对应的方法,先用SurfaceSession获取SurfaceComposerClient,然后调用createSurface方法,获取SurfaceControl。
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags) {
ScopedUtfChars name(env, nameStr);
sp client(android_view_SurfaceSession_getClient(env, sessionObj));
sp surface = client->createSurface(
String8(name.c_str()), w, h, format, flags);
if (surface == NULL) {
jniThrowException(env, OutOfResourcesException, NULL);
return 0;
}
surface->incStrong((void *)nativeCreate);
return reinterpret_cast(surface.get());
}
我们来看android_view_SurfaceSession_getClient就是获取SurfaceSession的mNativeObject对象,也就是SurfaceComposerClient对象。
sp android_view_SurfaceSession_getClient(
JNIEnv* env, jobject surfaceSessionObj) {
return reinterpret_cast(
env->GetLongField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
}
那么Session的成员变量mSurfaceSession又是什么时候创建的?
之前在分析ViewRootImpl的setView时候,会调用Session的addToDisplay函数,在这个函数调用了PKMS的addWindow函数,而在addWindow方法,后面会创建一个WindowState对象,然后调用了其attach方法。
......
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
......
win.attach();
我们来看下这个WindowState的attach方法,调用了Session的windowAddedLocked方法。
void attach() {
if (WindowManagerService.localLOGV) Slog.v(
TAG, "Attaching " + this + " token=" + mToken
+ ", list=" + mToken.windows);
mSession.windowAddedLocked();
}
在Session的windowAddedLocked方法中创建了SurfaceSession对象。
void windowAddedLocked() {
if (mSurfaceSession == null) {
if (WindowManagerService.localLOGV) Slog.v(
WindowManagerService.TAG, "First window added to " + this + ", creating SurfaceSession");
mSurfaceSession = new SurfaceSession();
if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
WindowManagerService.TAG, " NEW SURFACE SESSION " + mSurfaceSession);
mService.mSessions.add(this);
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
}
mNumWindow++;
}
在SurfaceSession构造函数中直接调用了nativeCreate JNI函数。
public SurfaceSession() {
mNativeClient = nativeCreate();
}
我们来看下这个JNI函数,创建了一个SurfaceComposerClient对象
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
client->incStrong((void*)nativeCreate);
return reinterpret_cast(client);
}
SurfaceComposerClient对象的构造函数也没有什么,因为SurfaceComposerClient类也是RefBase类派生的,所以我们来看下onFirstRef函数。
SurfaceComposerClient::SurfaceComposerClient()
: mStatus(NO_INIT), mComposer(Composer::getInstance())
{
}
void SurfaceComposerClient::onFirstRef() {
sp sm(ComposerService::getComposerService());
if (sm != 0) {
sp conn = sm->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
onFirstRef函数先调用了ComposerService的getComposerService方法来获取一个ISurfaceComposer的指针,然后调用它的createConnection来得到一个ISurfaceComposerClient的指针,并且保存在mClient成员变量中。
最后我们知道在SurfaceControl中是调用SurfaceComposerClient的createSurface来得到Surface对象的。
我们再来看ComposerService::getComposerService函数,调用了connectLocked函数
/*static*/ sp ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
assert(instance.mComposerService != NULL);
ALOGD("ComposerService reconnected");
}
return instance.mComposerService;
}
connectLocked函数只是获取SurfaceFlinger的Binder对象,然后保存在mComposerService。
void ComposerService::connectLocked() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
......
所以最后在SurfaceComposerClient的onFirstRef函数中,先是获取SurfaceFlinger的Binder对象,然后调用函数createConnection函数,最终也是到SurfaceFlinger的createConnection函数。我们来看SurfaceFlinger的createConnection函数,创建一个client对象(这也是一个Binder服务),最后返回这个对象。而返回的对象保存在SurfaceComposerClient类的mClient成员变量中。这样每一个连接都会有一个新的Client对象。
sp SurfaceFlinger::createConnection()
{
sp bclient;
sp client(new Client(this));
status_t err = client->initCheck();
if (err == NO_ERROR) {
bclient = client;
}
return bclient;
}
最后在SurfaceComposerClient中创建Surface,也是调用了mClient的createSurface,就到SurfaceFlinger的Client对象的createSurface函数了,获取了handle和gbp对象就创建了SurfaceControl对象。
sp SurfaceComposerClient::createSurface(
const String8& name,
uint32_t w,
uint32_t h,
PixelFormat format,
uint32_t flags)
{
sp sur;
if (mStatus == NO_ERROR) {
sp handle;
sp gbp;
status_t err = mClient->createSurface(name, w, h, format, flags,
&handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
sur = new SurfaceControl(this, handle, gbp);
}
}
return sur;
}
我们再来看SurfaceControl对象的构造函数就是初始化各种变量。
SurfaceControl::SurfaceControl(
const sp& client,
const sp& handle,
const sp& gbp)
: mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
{
}
最后通过getSurface来新建一个Surface对象,Surface对象一个重要的参数是mGraphicBufferProducer,而这个对象的一个参数就是gbp
sp SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
// This surface is always consumed by SurfaceFlinger, so the
// producerControlledByApp value doesn't matter; using false.
mSurfaceData = new Surface(mGraphicBufferProducer, false);
}
return mSurfaceData;
}