Android 图形系统详解
创始人
2024-05-23 16:44:44

概述

一个页面(Activity)显示到屏幕上主要经过一下几个流程:
启动 Activity → 创建 Window → WMS 注册 Window → SurfaceFlinger 创建 Surface → 合成 layer → 显示
主要涉及三个进程:App进程、System_server进程、SurfaceFlinger进程

  1. App 进程:负责发起 Surface 创建的请求。同时触发对控件的测量、布局、绘制以及输入事件的派发处理,主要在 ViewRootImpl中 触发( AMS 作用是统一调度所有 App 的 Activity )
  2. System_server 进程:主要是 WindowManagerService,负责接收 App 请求,同时和 SurfaceFlinger 建立连接,向 SF 发起具体请求创建 Surface,并且创建 Surace 的辅助管理类 SurfaceControl(与 window 一一对应)
  3. SurfaceFlinger:为 App 创建具体的 Surface,在 SurfaceFlinger 对应 Layer,然后负责管理、合成所有图层,最终显示在屏幕上
    在这里插入图片描述

应用层可通过两种方式将图像绘制到屏幕上:使用 Canvas 或 OpenGL

  • android.graphics.Canvas 是一个 2D 图形 API,从 4.0 开始通过 OpenGLRenderer 的绘制库实现硬件加速,将Canvas 运算转换为 OpenGL 运算,以便它们可以在 GPU 上执行,提升效率
  • OpenGL ES 直接渲染到 Surface ,Android 在 Android.opengl 软件包中提供了 OpenGL ES 接口
    下图是 view 绘制到 display 展示的整体流程,我们主要看左上角虚线框部分,整体分为 App 进程和系统进程两个部分
    在这里插入图片描述

App 进程

概念解释

  • Activity: 一个 Activity 对应创建一个 Surface,每个 Surface 对应 SurfaceFlinger 中的一个 Layer
  • Window:每个 Activity 包含一个 Window 对象(抽象类,提供绘制窗口的通用API),由 PhoneWindow 实现。是 Activity 和整个 View 系统交互的接口。
  • PhoneWindow: 继承于 Window,是 Window 类的具体实现。该类内部包含了一个 DecorView 对象,该对象是所有应用窗口(Activity 界面)的根 View。把一个 FrameLayout 类,即 DecorView 对象进行一定的包装,将他作为应用窗口的根 View,并提供一组通用的窗口操作接口。
  • DecorView:PhoneWindow setContentView 函数中创建,继承 FrameLayout,是所有应用窗口的根 View。
  • WindowManager :继承 ViewManager ,操作 UI 的接口,具备添加、删除和更新View,具体却委托给了WindowsManagerGlobal来进行实现
  • WindowManagerImpl: 实现了 WindowManager,并持有 WindowManagerGlobal 的对象
  • WindowManagerGlobal:单例模式,每个进程只有一个。持有 ViewRootImpl 的对象
  • ViewRootImpl:所有 View 的根,作为 View 与后台各种服务的桥梁。用户输入系统(接收用户按键,触摸屏输入)、窗口系统(复杂窗口的布局,刷新,动画)、显示合成系统(包括定时器Choreograph, SurfaceFlinger)等
  • Surface:app 层用于绘制的对象在这里插入图片描述

流程分析

在这里插入图片描述

源码分析


ActivityThread.java {private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {......activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);......activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.activityConfigCallback,r.assistToken, r.shareableActivityToken);......mInstrumentation.callActivityOnCreate(activity, r.state);}public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, String reason) {......wm.addView(decor, l);......}
}Activity.java {private Window mWindow;final void attach(......){......mWindow = new PhoneWindow(this, window, activityConfigCallback);......mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),mToken, mComponent.flattenToString(),(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);......}protected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState)setContentView(R.layout.activity);}public void setContentView(@LayoutRes int layoutResID) {getWindow().setContentView(layoutResID);initWindowDecorActionBar();}
}Window.java {private WindowManager mWindowManager;public void setWindowManager(WindowManager wm, IBinder appToken, String appName,boolean hardwareAccelerated) {......mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);......}
}PhoneWindow.java {private DecorView mDecor;public void setContentView(View view, ViewGroup.LayoutParams params) {......installDecor();......}private void installDecor() {......mDecor = generateDecor(-1);......}protected DecorView generateDecor(int featureId) {......return new DecorView(context, featureId, this, getAttributes());}
}
WindowManagerImpl.java {private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();public WindowManagerImpl createLocalWindowManager(Window parentWindow) {return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken);}public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {......mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,mContext.getUserId());}
}
WindowManagerGlobal.java {private final ArrayList mRoots = new ArrayList();public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow, int userId) {......ViewRootImpl root = new ViewRootImpl(view.getContext(), display);......root = new ViewRootImpl(view.getContext(), display);......mRoots.add(root);......root.setView(view, wparams, panelParentView, userId);......}
}ViewRootImpl.java {View mView;//DecorViewpublic final Surface mSurface = new Surface();private final SurfaceControl mSurfaceControl = new SurfaceControl();// 接收显示系统的时间脉冲(垂直同步信号- VSync 信号)// 同 Vsync 机制配合,控制同步处理输入(Input)、动画(Animation)、绘制(Draw)三个UI操作final Choreographer mChoreographer;public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId) {......mView = view;......mWindowSession.addToDisplayAsUser()......requestLayout();......}public void requestLayout() {......scheduleTraversals();......}final class TraversalRunnable implements Runnable {@Overridepublic void run() {doTraversal();}}final TraversalRunnable mTraversalRunnable = new TraversalRunnable();void scheduleTraversals() {......mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);......}void doTraversal() {......performTraversals();......}private void performTraversals() {......performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);......performLayout(lp, mWidth, mHeight);......performDraw()......}private boolean performDraw() {......draw(fullRedrawNeeded, usingAsyncReport && mSyncBuffer);......}private boolean draw(boolean fullRedrawNeeded, boolean forceDraw) {......drawSoftware(surface, mAttachInfo, xOffset, yOffset,scalingRequired, dirty, surfaceInsets);......}private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,boolean scalingRequired, Rect dirty, Rect surfaceInsets) {......canvas = mSurface.lockCanvas(dirty);......//DecorViewmView.draw(canvas);......surface.unlockCanvasAndPost(canvas);}
}

System 进程

概念解释

  • WindowToken:将同一应用组件(Activity、InputMethod、Wallpaper或者Dream)的窗口组织到一起

  • WindowState:表示一个窗口的所有属性,是 WMS 事实上的窗口
    在这里插入图片描述

  • WindowManagerService:为所有窗口分配 Surface、负责 Surface 的显示顺序(Z序)以及大小尺寸、控制窗口动画,并且还是输入系统的中转站

  • Surface:native 层用于处理窗口的大小位置裁剪等操作

  • SurfaceComposerClient:与 SurfaceFlinger 进行通信,代理对象 mClient,对应 SurfaceFlinger 的 Binder 本地 Client 对象

  • SurfaceControl: app 层 surface 向 native 层提交的 buffer 的控制逻辑

  • BufferQueue:数据的生产者(Surface、BufferQueueProducer)与消费者 (SurfaceFlinger、BufferQueueConsumer)

  • Layer:SurfaceFlinger 进行合成的基本操作单元,当应用创建 Surface 的时候在 SurfaceFlinger 内部创建Layer,因此一个 Surface 对应一个 Layer。

  • SurfaceFlinger:运行在独立进程的 Service, 接收所有 Window 的 Surface 作为输入,根据 Z-Order, 透明度,大小,位置等参数,计算出每个 Surface 在最终合成图像中的位置,然后交由 HWComposer 或 OpenGL 生成最终的显示 Buffer, 然后显示到设备上

对应关系:
Activity -> Window -> DecorView -> ViewRootImpl -> WindowState -> Surface -> Layer 是一一对应的。
在这里插入图片描述

流程分析

在这里插入图片描述

源码分析

SurfaceFlinger 启动

main_surfaceflinger.cpp {int main(int, char**) {......sp flinger = surfaceflinger::createSurfaceFlinger();......flinger->init();......// publish surface flingersp sm(defaultServiceManager());sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);......// run surface flinger in this threadflinger->run();}
}
SurfaceFlinger.cpp {void SurfaceFlinger::onFirstRef() {......mEventQueue.init(this);......}void SurfaceFlinger::init(){......// 初始化OpenGL 图形库相关配置mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);......// 创建显示设备的抽象代表,负责和显示设备打交道mHwc = new HWComposer(this, *static_cast(this));......// app的VSync信号,也就是Systrace中的VSync-app,它最终是发往到choreographer,// 主要处理三件事情INPUT、ANIMATION、TRAVERSAL// start the EventThreadsp vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app");mEventThread = new EventThread(vsyncSrc);......}void SurfaceFlinger::run() {do {//运行线程,等待数据waitForEvent();} while (true);}void SurfaceFlinger::waitForEvent() {mEventQueue.waitMessage();}// 发送数据status_t SurfaceFlinger::postMessageSync(const sp& msg,nsecs_t reltime, uint32_t /* flags */) {status_t res = mEventQueue.postMessage(msg, reltime);if (res == NO_ERROR) {msg->wait();}return res;}
}
MessageQueue.cpp {void MessageQueue::init(const sp& flinger) {mFlinger = flinger;mLooper = new Looper(true);mHandler = new Handler(*this);}status_t MessageQueue::postMessage(const sp& messageHandler, nsecs_t relTime) {const Message dummyMessage;if (relTime > 0) {mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);} else {mLooper->sendMessage(messageHandler, dummyMessage);}return NO_ERROR;}
}

创建 Native 层 Surface 以及 SurfaceFlinger 的 Layer

android_view_Surface.cpp {static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz, jlong nativeObject, jlong surfaceControlNativeObj) {Surface* self(reinterpret_cast(nativeObject));sp ctrl(reinterpret_cast(surfaceControlNativeObj));// If the underlying IGBP's are the same, we don't need to do anything.if (self != nullptr &&IInterface::asBinder(self->getIGraphicBufferProducer()) ==IInterface::asBinder(ctrl->getIGraphicBufferProducer())) {return nativeObject;}sp surface(ctrl->getSurface());if (surface != NULL) {surface->incStrong(&sRefBaseOwner);}return reinterpret_cast(surface.get());}
}
SurfaceControl.cpp {sp   mClient;sp SurfaceControl::getSurface() {Mutex::Autolock _l(mLock);if (mSurfaceData == nullptr) {return generateSurfaceLocked();}return mSurfaceData;}sp SurfaceControl::generateSurfaceLocked() {......mBbqChild = mClient->createSurface(String8("bbq-wrapper"), 0, 0, mFormat,flags, mHandle, {}, &ignore);// 当 buffer 入队后会回调 BLASTBufferQueue 的 onFrameAvailablemBbq = sp::make("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);// This surface is always consumed by SurfaceFlinger, so the// producerControlledByApp value doesn't matter; using false.mSurfaceData = mBbq->getSurface(true);return mSurfaceData;}
}SurfaceComposerClient.cpp {sp  mClient;sp SurfaceComposerClient::createSurface(const String8& name, DisplayID display,uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {sp result;if (mStatus == NO_ERROR) {ISurfaceComposerClient::surface_data_t data;sp surface = mClient->createSurface(&data, name, display, w, h, format, flags);if (surface != 0) {result = new SurfaceControl(this, surface, data);}}return result;}
}
Client.cpp {status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,sp* handle, sp* gbp) {......class MessageCreateLayer : public MessageBase {virtual bool handler() {//最后会执行这里 createLayerresult = flinger->createLayer(name, client, w, h, format, flags,handle, gbp);return true;}}sp msg = new MessageCreateLayer(mFlinger.get(),name, this, w, h, format, flags, handle, gbp);//这个mFlinger 就是SurfaceFlinger对象mFlinger->postMessageSync(msg);return static_cast( msg.get() )->getResult();}
}
SurfaceFlinger.cpp {status_t SurfaceFlinger::createLayer( const String8& name, const sp& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,sp* handle, sp* gbp) {......sp layer;......result = createNormalLayer(client, name, w, h, flags, format, handle, gbp, &layer);......addClientLayer(client, *handle, *gbp, layer);......return result;}status_t SurfaceFlinger::createNormalLayer(const sp& client,const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,sp* handle, sp* gbp, sp* outLayer){......*outLayer = new Layer(this, client, name, w, h, flags);......status_t err = (*outLayer)->setBuffers(w, h, format, flags);if (err == NO_ERROR) {*handle = (*outLayer)->getHandle();*gbp = (*outLayer)->getProducer();}......return err;}
}
Layer.cpp {void Layer::onFirstRef() {// Creates a custom BufferQueue for SurfaceFlingerConsumer to use//创建了生产者和消费者缓冲区,这两个缓冲区将来会存放UI的内容数据sp producer;sp consumer;......BufferQueue::createBufferQueue(&producer, &consumer);mProducer = new MonitoredProducer(producer, mFlinger);mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);......// 这里设置使用 双缓存 还是 三重缓存#ifdef TARGET_DISABLE_TRIPLE_BUFFERING#warning "disabling triple buffering"mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);#elsemSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);#endif......}
}

绘制

ViewRootImpl.java {private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,boolean scalingRequired, Rect dirty, Rect surfaceInsets) {......canvas = mSurface.lockCanvas(dirty);......mView.draw(canvas);......surface.unlockCanvasAndPost(canvas);......}
}android_view_Surface.cpp {static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {sp surface(reinterpret_cast(nativeObject));......ANativeWindow_Buffer buffer;//申请图形 bufferstatus_t err = surface->lock(&buffer, dirtyRectPtr);......graphics::Canvas canvas(env, canvasObj);canvas.setBuffer(&buffer, static_cast(surface->getBuffersDataSpace()));......sp lockedSurface(surface);lockedSurface->incStrong(&sRefBaseOwner);return (jlong) lockedSurface.get();}static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz, jlong nativeObject, jobject canvasObj) {sp surface(reinterpret_cast(nativeObject));......status_t err = surface->unlockAndPost();......}
}
Surface.cpp {sp mGraphicBufferProducer;status_t Surface::lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) {......status_t err = dequeueBuffer(&out, &fenceFd);......if (err == NO_ERROR) {......sp backBuffer(GraphicBuffer::getSelf(out));const Rect bounds(backBuffer->width, backBuffer->height);......}}int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {......status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, dqInput.width,dqInput.height, dqInput.format,dqInput.usage, &mBufferAge,dqInput.getTimestamps ? &frameTimestamps : nullptr);......}status_t Surface::unlockAndPost() {......status_t err = mLockedBuffer->unlockAsync(&fd);......err = queueBuffer(mLockedBuffer.get(), fd);......return err;}int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {......int i = getSlotFromBufferLocked(buffer);......status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);......onBufferQueuedLocked(i, fence, output);return err;}
}
BufferQueueProducer.cpp {status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp* outFence,uint32_t width, uint32_t height, PixelFormat format,uint64_t usage, uint64_t* outBufferAge,FrameEventHistoryDelta* outTimestamps) {......std::unique_lock lock(mCore->mMutex);......int found = BufferItem::INVALID_BUFFER_SLOT;while (found == BufferItem::INVALID_BUFFER_SLOT) {//从队列中取出一块已经 releas 的 bufferstatus_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found);if (status != NO_ERROR) {return status;}......}}status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,std::unique_lock& lock, int* found) const {......*found = getFreeBufferLocked();......}int BufferQueueProducer::getFreeBufferLocked() const {if (mCore->mFreeBuffers.empty()) {return BufferQueueCore::INVALID_BUFFER_SLOT;}int slot = mCore->mFreeBuffers.front();mCore->mFreeBuffers.pop_front();return slot;}status_t BufferQueueProducer::queueBuffer(int slot,const QueueBufferInput &input, QueueBufferOutput *output) {......const sp& graphicBuffer(mSlots[slot].mGraphicBuffer);Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());Rect croppedRect(Rect::EMPTY_RECT);crop.intersect(bufferRect, &croppedRect);......mSlots[slot].mFence = acquireFence;mSlots[slot].mBufferState.queue();......BufferItem item;// 相关数据封装成 BufferItem 并入队item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;......mCore->mQueue.push_back(item);......//取出 BufferQueueCore 的回调接口,下面调用这个接口的onFrameAvailable 函数,来通知SurfaceFlinger 进行渲染frameAvailableListener = mCore->mConsumerListener;......// 回调 BLASTBufferQueue 的 onFrameAvailableframeAvailableListener->onFrameAvailable(item);}
}
BLASTBufferQueue.cpp {void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {......SurfaceComposerClient::Transaction* prevTransaction = nullptr;......if (syncTransactionSet) {acquireNextBufferLocked(mSyncTransaction);// Only need a commit callback when syncing to ensure the buffer that's synced has been// sent to SFmSyncTransaction->addTransactionCommittedCallback(transactionCommittedCallbackThunk,static_cast(this));......if (mAcquireSingleBuffer) {prevCallback = mTransactionReadyCallback;prevTransaction = mSyncTransaction;......}}if (prevCallback) {prevCallback(prevTransaction);}}void BLASTBufferQueue::acquireNextBufferLocked(const std::optional transaction){......status_t status = mBufferItemConsumer->acquireBuffer(&bufferItem, 0 , false);......t = *transaction;......//将提交的 buffer 设置给 SurfaceComposerClient 去进行合成显示t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseBufferCallback);......mergePendingTransactions(t, bufferItem.mFrameNumber);......}
}
BufferQueueConsumer.cpp {status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,nsecs_t expectedPresent, uint64_t maxFrameNumber) {while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {......const BufferItem& bufferItem(mCore->mQueue[1]);......}......//填充相关数据outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;......//通知消费者该buffer可以重新使用了listener->onBufferReleased();}
}

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...