Android的UI控件最终在Surface上进行绘制;Surface要进行绘制,须要申请显存,绘制,提交显存进行显示。java
Android的显存由两个部分表示,对APP的接口体现为Surface(native/libs/gui/Surface.cpp),对graphics部分(CPU/GPU/OPENGL)体现为GraphicBuffer。android
Surface说明canvas
Surface自己有两个含义,一个是表明UI系统的Canvas,另外一个是表明本地window系统,为跨平台的OPENGL(EGL)提供接口。session
UI通常基于Canvas绘制,参考UI的始祖View的draw函数:app
public void draw(Canvas canvas)
全部UI控件继承自View,都会基于Canvs来绘制本身;UI组件的draw是谁触发的,canvas是怎么建立的?这些秘密在ViewRootImpl里面,每一个Activity在setContentView以后,系统会为其建立一个ViewRootImpl对象,该对象代替Activity管理其view系统,并和window系统创建关联(Activity的window就是在该类中建立的),而且ViewRootImpl会创建和SurfaceFlinger的链接,监听SurfaceFlinger的VSYNC信号,一旦VSYNC信号发生,ViewRootImpl就会进入到framecallback中进行绘制。其中ViewRootImpl拥有window对应的Surface对象:ide
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff, boolean scalingRequired, Rect dirty, Rect surfaceInsets) { // Draw with software renderer. final Canvas canvas;try { ...... canvas = mSurface.lockCanvas(dirty); ...... if (!canvas.isOpaque() || yoff != 0 || xoff != 0) { canvas.drawColor(0, PorterDuff.Mode.CLEAR); } try { canvas.translate(-xoff, -yoff); ....... mView.draw(canvas); } finally { ...... } } finally { try { surface.unlockCanvasAndPost(canvas); } catch (IllegalArgumentException e) ...... }
对于Canvas的使用流程:函数
Surface.lockCanvas->View.draw(Canvas)-> Surface.unlockCanvasAndPost(Canvas)ui
在Surface.lockCanvas中会调用native的对象android_view_Surface.cpp->Surface.dequeueBuffer->BufferQueueProducer.dequeueBuffer获得struct ANativeWindowBuffer 的对象,其实就是一个GraphicBuffer对象,与此同时还返回了FenceID。 this
ANativeWindow_Buffer outBuffer; status_t err = surface->lock(&outBuffer, dirtyRectPtr); if (err < 0) { const char* const exception = (err == NO_MEMORY) ? OutOfResourcesException : "java/lang/IllegalArgumentException"; jniThrowException(env, exception, NULL); return 0; } SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height, convertPixelFormat(outBuffer.format), outBuffer.format == PIXEL_FORMAT_RGBX_8888 ? kOpaque_SkAlphaType : kPremul_SkAlphaType, GraphicsJNI::defaultColorSpace()); SkBitmap bitmap; ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format); bitmap.setInfo(info, bpr); if (outBuffer.width > 0 && outBuffer.height > 0) { bitmap.setPixels(outBuffer.bits); } else { // be safe with an empty bitmap. bitmap.setPixels(NULL); } Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj); nativeCanvas->setBitmap(bitmap);
由上面的lockCanvas代码片断来看,根据ANativeWindowBuffer构建了一个SKBitmap对象,将该对象设置给nativeCanvas(SkiaCanvas),而后就返回到Java空间了。spa
上面提到了Canvas,咱们看一下Canvas的处理流程。
大部分基于Canvas的操做最后会落到SKCanvas上面去,这个在Skia 2D库里面。若是想搞清楚流程,能够拿TextView或者Android任意一个UI控件,看一下他的draw是怎么利用canvas API来实现的。也能够看一下skia库实现。
在UI绘制完成后,须要将绘制的内容提交显示,这里用到了Surface::unlockAndPost:
status_t Surface::unlockAndPost() { if (mLockedBuffer == 0) { ALOGE("Surface::unlockAndPost failed, no locked buffer"); return INVALID_OPERATION; } int fd = -1; status_t err = mLockedBuffer->unlockAsync(&fd); ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle); err = queueBuffer(mLockedBuffer.get(), fd); ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)", mLockedBuffer->handle, strerror(-err)); mPostedBuffer = mLockedBuffer; mLockedBuffer = 0; return err; }
其中主要就是将GraphicBuffer 提交到BufferQueue上等待SurfaceFlinger(comsumer)显示出来。
BufferQueue的基本结构以下:
GraphicBuffer就与基于BufferQueueProducer产生的,在Surface.cpp里面有一个sp<IGraphicsBufferProducer> mGraphicBufferProducer;全部对GraphicBuffer的queue/dequeue/cancel等都是经过mBufferProducer产生的,咱们看一下这个对象是怎么产生,谁在server端为其服务,client和server的链接是怎么创建的。
从前面Surface的说明里面咱们提到一点,就是ViewRootImpl;ViewRootImpl里面的Surface为全部View的绘制提供canvas,咱们看一下这个Surface是怎么建立的就能搞清楚Surface.mGraphicBufferProducer是怎么实例化的。ViewRootImpl是Activity View管理者,也是Activity对应window的建立者,在其中有几个步骤:
create window,就是建立Activity对应的window对象,是和WMS创建通信建立窗口
try { mOrigWindowType = mWindowAttributes.type; mAttachInfo.mRecomputeGlobalAttributes = true; collectViewAttributes(); res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mWinFrame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel); } catch (RemoteException e) { mAdded = false;
relayout window,测量窗口大小位置等:
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);
在WMS里面上面两个接口分别调用addWindow以及relayoutWindow;其中relayoutWindow中建立了实际的surface,也就是说实在WMS中显示窗口的时候去建立了实际的surface,其建立过程以下:
最后是调用surface.copyFrom(SurfaceControl)获得真实的surface;SurfaceControl是在WMS里面建立的,SurfaceControl建立的时候就会向SurfaceComposerClient申请建立surface:
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject, jint windowType, jint ownerUid) { ScopedUtfChars name(env, nameStr); sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject); sp<SurfaceControl> surface; status_t err = client->createSurfaceChecked( String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid); if (err == NAME_NOT_FOUND) { jniThrowException(env, "java/lang/IllegalArgumentException", NULL); return 0; } else if (err != NO_ERROR) { jniThrowException(env, OutOfResourcesException, NULL); return 0; } surface->incStrong((void *)nativeCreate); return reinterpret_cast<jlong>(surface.get()); }
在createSurfaceChecked里面想surfaceFlinger申请建立Surface,并基于建立的Surface建立新的SurfaceControl。而后一步步返回,ViewRootImpl里面的Surface就具有真正的显存了。可是咱们前面是要知道GraphicBufferProducer是谁建立的,这个秘密就在ComposerSurfaceClient.createSurfaceChecked函数里面。ComposerSurfaceClient有一个成员变量mClient,这是SurfaceFlinger.Client的客户端,经过这个mClient和SurfaceFlinger创建通信。
status_t SurfaceComposerClient::createSurfaceChecked(...) { sp<SurfaceControl> sur; status_t err = mStatus; if (mStatus == NO_ERROR) { sp<IBinder> handle; sp<IBinder> parentHandle; sp<IGraphicBufferProducer> gbp; if (parent != nullptr) { parentHandle = parent->getHandle(); } err = mClient->createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */); } } return err; }
在这里能够看到调用了mClient的createSurface,而后返回了gbp(也就是IGraphicBufferProducer);mClient是SurfaceFlinger.Client的客户端,因而可知GraphicBufferProducer实际是有SurfaceFlinger进程建立的。mClient和SurfaceFlinger的对象关系以下图所示:
那么进入SurfaceFlinger看一下究竟是怎么建立GraphicBufferProducer的;Client.createSurface->SurfaceFlinger.createLayer-> new BufferLayer,实际是在BufferLayer::onFirstRef里面建立的:
void BufferLayer::onFirstRef() { // Creates a custom BufferQueue for SurfaceFlingerConsumer to use sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer, true); mProducer = new MonitoredProducer(producer, mFlinger, this); mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName); if (mFlinger->isLayerTripleBufferingDisabled()) { mProducer->setMaxDequeuedBufferCount(2); } const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); updateTransformHint(hw); }
由上面的建立过程也能够看出来,Surface提交的GraphicBuffer由BufferLayerConsumer来消耗。