最近有些忙,切实体验了一把拖更的羞耻感 ( *︾▽︾)java
本文和上一篇深刻Android系统(十二)Android图形显示系统-1-显示原理与Surface关系比较密切,撸完前篇更易理解本文啦 (๑‾ ꇴ ‾๑)android
了解SurfaceFlinger
以前咱们须要先了解下OpenGL
相关的一些知识git
OpenGL ES
与EGL
OpenGL
通常OpenGL
被认为是一个API
(Application Programming Interface, 应用程序编程接口),包含了一系列能够操做图形、图像的函数。然而,OpenGL
自己并非一个API,它仅仅是一个由Khronos
组织制定并维护的规范(Specification)。github
OpenGL规范
严格规定了每一个函数该如何执行,以及它们的输出值。至于内部具体每一个函数是如何实现的,将由OpenGL
库的开发者自行决定算法
实际的OpenGL
库的开发者一般是显卡的生产商编程
OpenGL ES(OpenGL for Embedded Systems)
是从OpenGL
裁剪的定制而来的,去除了一些复杂图元等许多非绝对必要的特性markdown
OpenGL
仍是很值得学习的,你们能够参考:LearnOpenGL教程的中文翻译app
EGL
咱们知道OpenGL ES
定义了一个渲染图形的API
,但没有定义窗口系统。异步
为了让OpenGL ES
可以适合各类平台,OpenGL ES
须要与一个知道如何经过操做系统建立和访问窗口的库结合使用socket
在Android
中的这个库就是EGL
。(没有什么问题是不能经过增长一个中间层来解决的,有的话那就再增长一个。。。。。)
总体结构以下(网上盗图):
EGL
的用法使用EGL
绘制的通常步骤以下:
Android
中的封装前面的章节咱们介绍过,不管开发者使用什么渲染API,一切内容都会渲染到Surface
上
Surface
指的是framework/native/libs/gui/Surface.cpp
对应的业务逻辑当SurfaceFlinger
以消费者的角色获取到显示数据后,会开始进行渲染操做,在过程当中也存在一个Surface
framework/native/services/surfaceflinger/RenderEngine/Surface.cpp
Surface
即是对EGL
接口的调用封装,咱们看下这个类的定义: Surface::Surface(const RenderEngine& engine)
: mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
...
}
Surface::~Surface() {
setNativeWindow(nullptr);
}
void Surface::setNativeWindow(ANativeWindow* window) {
...
if (mWindow) {
mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr);
}
}
void Surface::swapBuffers() const {
if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
...
}
}
EGLint Surface::queryConfig(EGLint attrib) const {
EGLint value;
if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
value = 0;
}
return value;
}
EGLint Surface::querySurface(EGLint attrib) const {
EGLint value;
if (!eglQuerySurface(mEGLDisplay, mEGLSurface, attrib, &value)) {
value = 0;
}
return value;
}
复制代码
接口定义结合上面EGL
的知识应该很容易理解,下面咱们开始SurfaceFlinger
学习吧
SurfaceFlinger
的启动过程从Android 4.4
开始SurfaceFlinger
服务运行在一个独立的守护进程中(之前在SystemServer
中),这样系统的图像绘制性能会获得必定的提高。frameworks/native/services/surfaceflinger/surfaceflinger.rc
中关于SurfaceFlinger
的定义以下:
service surfaceflinger /system/bin/surfaceflinger
class core animation user system group graphics drmrpc readproc onrestart restart zygote ... 复制代码
能够看到surfaceflinger
放到了core
组里,这个组的服务会在系统初始化时启动。SurfaceFlinger
启动的入口函数main()
代码以下:
int main(int, char**) {
...
// 启动 Gralloc 服务
startGraphicsAllocatorService();
// 设置当前Binder服务可链接最大线程数
ProcessState::self()->setThreadPoolMaxThreadCount(4);
// 经过 startThreadPool 通知 Binder 驱动当前线程已准备完成
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
// 初始化 SurfaceFlinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();
// 调整进程优先级为 PRIORITY_URGENT_DISPLAY
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
// 调整调度策略,将其设置为前台进程
// 这两种标志涉及了内核的 彻底公平调度算法,感兴趣的同窗能够百度一下
// 在这里的目的是保证 SurfaceFlinger 的较高优先级,方便快速响应更新图像的请求
set_sched_policy(0, SP_FOREGROUND);
...
// 注册 Service 前的初始化部分
flinger->init();
// 注册 SurfaceFlinger 服务
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
// 注册 GpuService 服务
sp<GpuService> gpuservice = new GpuService();
sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
// 启动 DisplayService 服务
startDisplayService(); // dependency on SF getting registered above
...
// run surface flinger in this thread
flinger->run();
return 0;
}
复制代码
main()
方法中注释比较详细就不细说了,方法总结下来有三点:
GraphicsAllocatorService
、DisplayService
和GpuService
服务set_sched_policy
和sched_setscheduler
设置进程优先级SurfaceFlinger
对象的初始化以及init
和run
方法的调用SurfaceFlinger
的初始化过程设计的模块比较多,咱们先简单看下类关系图:
SurfaceFlinger
对象初始化SurfaceFlinger
的类定义以下:
class SurfaceFlinger : public BnSurfaceComposer,
public PriorityDumper,
private IBinder::DeathRecipient,
private HWC2::ComposerCallback
{}
复制代码
BnSurfaceComposer
类:类图中该类实现的是ISurfaceComposer
接口,而ISurfaceComposer
又是一套定义好的Binder
类
Binder
篇提到过,当出现Bn*
开头的类就能够把它看作Binder服务类
了,因此SurfaceFlinger
这里是做为一个Binder
服务对象SurfaceSession
初始化时,SurfaceComposerClient
对象就是经过ServiceManager
获取了SurfaceFlinger
服务createConnection()
方法获取了ISurfaceComposerClient
对象,也就是上面类图中提到的Client
类HWC2::ComposerCallback
类:面向底层硬件状态的监听回调接口,包括
onHotplugReceived
,显示屏热插拔事件回调onRefreshReceived
,通知刷新的回调onVsyncReceived
,VSYNC
信号接收回调SurfaceFlinger
的构造方法以下:
SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
// 初始化 vsync 信号相关的 offset
vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
...
// 确认主屏幕方向
V1_1::DisplayOrientation primaryDisplayOrientation =
getDisplayOrientation< V1_1::ISurfaceFlingerConfigs, &V1_1::ISurfaceFlingerConfigs::primaryDisplayOrientation>(
V1_1::DisplayOrientation::ORIENTATION_0);
switch (primaryDisplayOrientation) {
case V1_1::DisplayOrientation::ORIENTATION_90:
mPrimaryDisplayOrientation = DisplayState::eOrientation90;
break;
...
}
// 初始化主屏幕的 DispSync 对象,这个对象与 vsync 信号分发有关系
mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset);
...
// 读取 Prop 进行一些基础属性的设置
// 是否启动 HWC 虚拟显示
property_get("debug.sf.enable_hwc_vds", value, "0");
mUseHwcVirtualDisplays = atoi(value);
// 是否开启三级缓冲
property_get("ro.sf.disable_triple_buffer", value, "1");
mLayerTripleBufferingDisabled = atoi(value);
...
}
复制代码
构造方法中主要的动做是mPrimaryDispSync.init()
操做,余下基本都是对一些变量的初始化。mPrimaryDispSync
的类型是DispSync
,这个对象主要是对VSYNC
信号进行调整,而后转发给app
或sf
,等下完善。
随着SurfaceFlinger
对象建立后的初次引用,也会调用到对象的onFirstRef()
方法:
void SurfaceFlinger::onFirstRef() {
mEventQueue->init(this);
}
复制代码
方法中执行了MessageQueue
对象的init()
方法,这个MessageQueue
是SurfaceFlinger
本身定义的消息队列,MessageQueue
相关的知识对整个SurfaceFlinger
业务逻辑的理解有着关键做用,下面细讲
了解这部分的内容有助于更好的理解
SurfaceFlinger
后面的init()
和run()
方法
MessageQueue
MessageQueue
是SurfaceFlinger
中用与消息和事件分发的对象,先看下主要的成员变量:
class MessageQueue{
...
sp<SurfaceFlinger> mFlinger; // 指向 SurfaceFlinger 对象
sp<Looper> mLooper; // 实现消息机制的 Looper 对象
android::EventThread* mEventThread; // 关联的 EventThread 对象
sp<IDisplayEventConnection> mEvents;
gui::BitTube mEventTube;
sp<Handler> mHandler; // 消息处理 Handler
...
}
复制代码
MessageQueue
的成员变量中
mLooper
是一个指向Looper
类的指针,它实现了一套完整的消息处理机制mEventThread
指向一个EventThread
对象,主要做用是分发VSYNC
信号前面提到在SurfaceFlinger
中会调用MessageQueue
对象的init()
方法,代码以下:
void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
mFlinger = flinger;
mLooper = new Looper(true);
mHandler = new Handler(*this);
}
复制代码
init()
方法中
建立了Handler
对象。此处的Handler
是MessageQueue
中定义的一个内部类,定义以下:
class MessageQueue final : public android::MessageQueue {
class Handler : public MessageHandler {
enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 };
MessageQueue& mQueue;
int32_t mEventMask;
...
};
}
复制代码
Handler
对象中主要处理三种消息:eventMaskInvalidate
、eventMaskRefresh
、eventMaskTransaction
建立了Looper
对象。关于native
层的Looper
对象在Android 消息机制
中已经介绍过,会经过epoll
开启一个消息监听,具体能够看这个直达入口
init()
完成后,MessageQueue
就能够经过waitMessage()
来等待消息,代码以下:
void MessageQueue::waitMessage() {
do {
IPCThreadState::self()->flushCommands();
int32_t ret = mLooper->pollOnce(-1); // 尝试读取消息,-1 表示永远阻塞
switch (ret) {
case Looper::POLL_WAKE: // poll 被唤醒
case Looper::POLL_CALLBACK:
continue;
case Looper::POLL_ERROR: // poll 发送错误
ALOGE("Looper::POLL_ERROR");
continue;
case Looper::POLL_TIMEOUT: // poll 超时
// timeout (should not happen)
continue;
default:
// should not happen
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
continue;
}
} while (true);
}
复制代码
waitMessage()
是一个无限循环,它的主要做用是循环调用Looper
类的pollOnce()
从消息队列中读取消息
须要注意的是waitMessage()
中并无消息的处理过程,并且没有明显的消息处理方法的调用,那么具体的消息处理在哪里?
消息的处理涉及EventThread
类,在MessageQueue
中经过setEventThread()
方法进行关联,代码以下:
void MessageQueue::setEventThread(android::EventThread* eventThread) {
if (mEventThread == eventThread) {
return;
}
if (mEventTube.getFd() >= 0) {
mLooper->removeFd(mEventTube.getFd());
}
mEventThread = eventThread;
// 建立链接
mEvents = eventThread->createEventConnection();
mEvents->stealReceiveChannel(&mEventTube);
// 重点是这个方法
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver, this);
}
复制代码
setEventThread()
方法中
EventThread
对象的createEventConnection()
方法来建立一个链接
EventThread
是一个线程类,用于分发VSYNC
消息,EventThread
内部会维护一个gui::BitTube mChannel
用于通讯,建立过程以下:sp<BnDisplayEventConnection> EventThread::createEventConnection() const {
// 建立 Connection 对象,同时会调用它的 onFirstRef 方法
return new Connection(const_cast<EventThread*>(this));
}
// Connection 的构造方法,初始化 BitTube mChannel 对象,并设置 mEventThread
EventThread::Connection::Connection(EventThread* eventThread)
: count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}
// Connection 对象的 onFirstRef 方法会将本身添加到 EventThread 中的 mDisplayEventConnections 中
void EventThread::Connection::onFirstRef() {
// NOTE: mEventThread doesn't hold a strong reference on us
mEventThread->registerDisplayEventConnection(this);
}
// 将 connection 对象添加到 mDisplayEventConnections 监听集合中
status_t EventThread::registerDisplayEventConnection( const sp<EventThread::Connection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
// 添加到 mDisplayEventConnections 集合中
mDisplayEventConnections.add(connection);
mCondition.notify_all();
return NO_ERROR;
}
复制代码
createEventConnection()
方法返回的是一个IDisplayEventConnection
对象mEvents
IDisplayEventConnection
对象的stealReceiveChannel()
方法
mEventTube
对象的mReceiveFd
,mEventTube
的类型是BitTube
BitTube
对象中包含一对Fd
:mReceiveFd
和mSendFd
,初始化时会经过socketpair()
建立全双工通讯Looper
类的addFd()
方法将mReceiveFd
添加到epoll
监听列表中,而且传入了MessageQueue::cb_eventReceiver
做为事件的回调方法
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
MessageQueue* queue = reinterpret_cast<MessageQueue*>(data);
return queue->eventReceiver(fd, events);
}
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
for (int i = 0; i < n; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
mHandler->dispatchInvalidate();
break;
}
}
}
return 1;
}
复制代码
mHandler->dispatchInvalidate();
方法,这就会涉及到Handler
的处理逻辑咱们看下Handler
中的处理逻辑:
void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
case INVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case REFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
复制代码
调用了SurfaceFlinger
的onMessageReceived()
方法,这里才是真正处理消息的地方,后面细讲这个方法哈
咱们先看下EventThread
类
EventThread
EventThread
的继承关系以下:
class EventThread : public android::EventThread, private VSyncSource::Callback {
}
复制代码
须要注意的是VSyncSource::Callback
类,它提供了一个onVSyncEvent()
的回调方法
EventThread
的构造方法以下(精简版):
EventThread::EventThread(...){
...
// 建立线程并开始执行,核心业务经过 threadMain() 方法来完成
mThread = std::thread(&EventThread::threadMain, this);
// 设置一些线程的名称和优先级
pthread_setname_np(mThread.native_handle(), threadName);
...
// 设置调度策略为 SP_FOREGROUND
set_sched_policy(tid, SP_FOREGROUND);
}
复制代码
构造方法中启动了一个线程,这个线程的执行逻辑在threadMain()
方法中:
void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
// mKeepRunning 只会在析构函数中置为 false
while (mKeepRunning) {
DisplayEventReceiver::Event event;
Vector<sp<EventThread::Connection> > signalConnections;
// 经过 waitForEventLocked() 循环等待事件
// 方法中会经过 mCondition 对象的 wait() 方法进行等待
signalConnections = waitForEventLocked(&lock, &event);
const size_t count = signalConnections.size();
for (size_t i = 0; i < count; i++) {
const sp<Connection>& conn(signalConnections[i]);
// 经过 postEvent() 将事件通知到到 MessageQueue
status_t err = conn->postEvent(event);
...
}
}
}
复制代码
threadMain()
方法中的重点是:
waitForEventLocked()
方法会循环等待消息(也就是VSYNC
信号),并获取到注册的Connection
对象列表Connection
对象的postEvent()
将数据发送到MessageQueue
MessageQueue
中的Looper
会检测到数据输入,而后通知回调MessageQueue
的cb_eventReceiver()
方法前面讲过VSYNC
信号由HWC
产生,为了方便接收,HWComposer
提供了一个HW2::ComposerCallback
用于监听消息
class ComposerCallback {
public:
virtual void onHotplugReceived(...) = 0;
virtual void onRefreshReceived(...) = 0;
virtual void onVsyncReceived(...) = 0;
virtual ~ComposerCallback() = default;
};
复制代码
SurfaceFlinger
继承该类,咱们重点关注onVsyncReceived()
方法SurfaceFlinger::onVsyncReceived()
方法以下:
void SurfaceFlinger::onVsyncReceived(...) {
...
bool needsHwVsync = false;
{ // Scope for the lock
Mutex::Autolock _l(mHWVsyncLock);
if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) {
// 经过 addResyncSample 来进一步分发信号
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
}
...
}
复制代码
onVsyncReceived()
方法调用mPrimaryDispSync
对象的addResyncSample()
方法来进一步分发VSYNC
信号
mPrimaryDispSync
对象的类型是DispSync
,这个类比较简单,核心是它的成员变量mThread
,类型是DispSyncThread
DispSyncThread
是一个线程类,在DispSync
对象初始化时进行建立,代码以下: DispSync::DispSync(const char* name)
: mName(name), mRefreshSkipCount(0), mThread(new DispSyncThread(name)) {}
复制代码
SurfaceFlinger
的构造方法中会调用DispSync
对象的init()
进行DispSyncThread
线程的启动 void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
...
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
...
}
复制代码
addResyncSample()
方法中最重要的是执行了DispSyncThread
对象的updateModel()
方法:
void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
... // 省略和 VSYNC 信号相关的一些赋值操做
// 重点是此处经过 Conditon.signal() 来唤醒 DispSyncThread 线程
mCond.signal();
}
复制代码
DispSyncThread
线程的执行函数以下:
virtual bool threadLoop() {
...
while (true) {
Vector<CallbackInvocation> callbackInvocations;
nsecs_t targetTime = 0;
{ // Scope for lock
...
if (now < targetTime) {
if (targetTime == INT64_MAX) {
err = mCond.wait(mMutex);
} else {
err = mCond.waitRelative(mMutex, targetTime - now);
}
...
}
now = systemTime(SYSTEM_TIME_MONOTONIC);
...
// 取得 Callback 列表
callbackInvocations = gatherCallbackInvocationsLocked(now);
}
// 经过 fireCallbackInvocations() 调用
if (callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations);
}
}
return false;
}
复制代码
threadLoop()
中大部分是比较和计算时间,决定是否要发送信号
mCond
上等待
updateModel()
中须要调用mCond
的signal()
来唤醒的缘由gatherCallbackInvocationsLocked()
获取本次VSYNC
信号回调通知的监听对象
addEventListener()
方法进行添加fireCallbackInvocations()
方法一次调用列表中全部对象的onDispSyncEvent()
方法 void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
if (kTraceDetailedInfo) ATRACE_CALL();
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}
复制代码
CallbackInvocation
结构就会发现,回调接口的类型是DispSync::Callback
那么SurfaceFlinger
中哪几个类实现了DispSync::Callback
呢?
聪明的咱们会发现,SurfaceFlinger
中的DispSyncSource
继承了这个类,并且重点是下面部分的代码:
class DispSyncSource final : public VSyncSource, private DispSync::Callback {
public:
...
void setVSyncEnabled(bool enable) override {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
status_t err = mDispSync->addEventListener(mName, mPhaseOffset, static_cast<DispSync::Callback*>(this));
...
} else {
status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this));
...
}
mEnabled = enable;
}
...
private:
virtual void onDispSyncEvent(nsecs_t when) {
VSyncSource::Callback* callback;
... // 省略 VSYNC 信号处理的一些操做
callback = mCallback;
if (callback != nullptr) {
callback->onVSyncEvent(when);
}
}
...
}
复制代码
能够发现:
DispSyncSource
对象的setVSyncEnabled()
方法时会注册DispSync
的事件监听onDispSyncEvent()
方法中最终调用了VSyncSource::Callback
对象的onVSyncEvent()
方法VSyncSource::Callback
对象又是和谁关联呢?
还记得前面的EventThread
么!!!EventThread
即是继承了VSyncSource::Callback
类,咱们看下EventThread
中关于onVSyncEvent()
方法的实现:
void EventThread::onVSyncEvent(nsecs_t timestamp) {
std::lock_guard<std::mutex> lock(mMutex);
mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[0].header.id = 0;
mVSyncEvent[0].header.timestamp = timestamp;
mVSyncEvent[0].vsync.count++;
mCondition.notify_all();
}
复制代码
前面EventThread
部分提到过
threadMain
中的waitForEventLocked()
会经过mCondition.wait()
等待消息,onVSyncEvent()
会经过notify_all()
唤醒threadMain
处理消息conn->postEvent(event);
方法postEvent()
方法会经过BitTube
对象将数据发送到MessageQueue
中MessageQueue
的cb_eventReceiver()
方法前面MessageQueue
章节提到过,cb_eventReceiver()
方法最后会调用的是SurfaceFlinger
的onMessageReceived()
方法,并且消息类型是INVALIDATE
。
咱们看下方法内容:
void SurfaceFlinger::onMessageReceived(int32_t what) {
switch (what) {
case MessageQueue::INVALIDATE: {
...
bool refreshNeeded = handleMessageTransaction();
...
break;
}
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
}
}
复制代码
INVALIDATE
消息的处理逻辑比较复杂,咱们重点关注的是handleMessageTransaction()
方法,它会建立DisplayDevice
对象。咱们先看下DisplayDevice
对象
DisplayDevice
DisplayDevice
类是显示设备的抽象,当前Android 9
中定义了3种显示设备类型:
DISPLAY_PRIMARY
:主显示设备DISPLAY_EXTERNAL
:扩展显示设备,经过HDMI
输出的显示信号DISPLAY_VIRTUAL
:虚拟显示设备,经过WIFI
输出的显示信号这三种显示设备,第一种是基本配置,另外两种须要硬件支持。关于Display
官网有个极其简单的介绍:传送门
在SurfaceFlinger
中DisplayDevice
负责与OpenGL ES
交互,即便没有任何物理显示设备被检测到,SurfaceFlinger
都须要一个DisplayDevice
对象才能正常工做
SurfaceFlinger
将须要显示的图层Layer
经过DisplayDevice
对象传递到OpenGL ES
中进行合成,合成后再经过HWComposer
对象传送到FrameBuffer
中显示
DisplayDevice
对象中的成员变量Vector< sp<Layer> > mVisibleLayersSortedByZ;
保存了全部须要在本设备中显示的Layer
对象
DisplayDevice
比较复杂,先简单了解下它的建立流程。前面提到了handleMessageTransaction()
方法中会建立DisplayDevice
对象,咱们看下具体的建立流程:
handleMessageTransaction()
-->handleTransactionLocked()
-->processDisplayChangesLocked()
void SurfaceFlinger::processDisplayChangesLocked() {
...
if (!curr.isIdenticalTo(draw)) {
...
for (size_t i = 0; i < cc; i++) {
if (draw.indexOfKey(curr.keyAt(i)) < 0) {
const DisplayDeviceState& state(curr[i]);
sp<DisplaySurface> dispSurface;
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferProducer> bqProducer;
sp<IGraphicBufferConsumer> bqConsumer;
// mCreateBufferQueue是一个函数指针,指向的是 BufferQueue::createBufferQueue
// 这就很熟悉了,和咱们前面分析 Surface 时建立的 BufferQueue 同样
mCreateBufferQueue(&bqProducer, &bqConsumer, false);
int32_t hwcId = -1;
if (state.isVirtualDisplay()) {
... // 省略虚拟屏幕建立的逻辑
} else {
...
hwcId = state.type;
// 建立 FramebufferSurface 用于数据传输
dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer);
producer = bqProducer;
}
const wp<IBinder>& display(curr.keyAt(i));
if (dispSurface != nullptr) {
// 经过 setupNewDisplayDeviceInternal() 建立 DisplayDevice 对象
// 并添加到 mDisplays 集合中
mDisplays.add(display, setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface, producer));
if (!state.isVirtualDisplay()) {
mEventThread->onHotplugReceived(state.type, true);
}
}
}
}
}
mDrawingState.displays = mCurrentState.displays;
}
复制代码
BufferQueue::createBufferQueue
建立了consumer
和producer
对象(这部分和前面讲的BufferQueue
的逻辑是相同的)consumer
对象和一个HWComposer
对象建立了一个FramebufferSurface
对象setupNewDisplayDeviceInternal()
方法建立DisplayDevice
对象,并添加到mDisplays
集合中sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state, const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
...
// mCreateNativeWindowSurface 也是一个函数指针,执行的是 NativeWindowSurface::create() 方法
// 该方法利用 IGraphicBufferProducer 生成 NativeWindowSurface 和 NativeWindow 对象
// 其实也是 EGL 相关的接口调用
auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
auto nativeWindow = nativeWindowSurface->getNativeWindow();
// 经过渲染引擎建立 OpenGL 渲染的目标 EGLSurface
std::unique_ptr<RE::Surface> renderSurface = getRenderEngine().createSurface();
renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY);
renderSurface->setAsync(state.type >= DisplayDevice::DISPLAY_VIRTUAL);
// 执行 eglCreateWindowSurface 操做
renderSurface->setNativeWindow(nativeWindow.get());
...
// 建立 DisplayDevice 对象
sp<DisplayDevice> hw = new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
dispSurface, std::move(renderSurface), displayWidth, displayHeight,
hasWideColorGamut, hdrCapabilities,
supportedPerFrameMetadata, hwcColorModes, initialPowerMode);
...
return hw;
}
复制代码
DisplayDevice
对象建立完成,意味着SurfaceFlinger
就能够利用DisplayDevice
对象写入图像数据,并经过
这样一条路径到达显示设备的FrameBuffer
中
SurfaceFlinger
的init()
和run()
有了前面的铺垫知识,init()
和run()
就很好理解了
SurfaceFlinger::init
void SurfaceFlinger::init() {
// 建立 app 的 DispSyncSource 和 EventThread
mEventThreadSource = std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
mEventThread = std::make_unique<impl::EventThread>(mEventThreadSource.get(), ..., "appEventThread");
// 建立 sf 的 DispSyncSource 和 EventThread
mSfEventThreadSource = std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = std::make_unique<impl::EventThread>(mSfEventThreadSource.get(), ..., "sfEventThread");
// 将 mSFEventThread 与 MessageQueue 进行关联
mEventQueue->setEventThread(mSFEventThread.get());
// 将 mSFEventThread 和 mEventThread 添加到 VSYNC 信号调制器中
mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
// 建立渲染引擎,主要是选择EGL配置,选择OpenGL版本,建立OpenGL上下文
getBE().mRenderEngine = RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,...);
...
// 初始化 HWC
getBE().mHwc.reset( new HWComposer(std::make_unique<Hwc2::impl::Composer>(getBE().mHwcServiceName)));
// 注册 HWC 的 Callback 监听
// VSYNC 信号便会从这里进行回调通知
getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
...
// 建立 VSYNC 事件接收控制对象,enable=true 表示容许 HWC 产生 VSYNC 信号
// sufacefinlger 经过这个对象来控制 HWC 是否产生 VSYNC 信号
mEventControlThread = std::make_unique<impl::EventControlThread>([this](bool enabled) { setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled); });
...
// 该方法会经过 MessageQueue 发送一个异步消息
// 消息处理中会完成 primary DisplayDevice 的建立,并进行 VSYNC 周期的设定
initializeDisplays();
...
// 根据 PresentFenceIsNotReliable 属性建立 StartPropertySetThread对象
if (getHwComposer().hasCapability(HWC2::Capability::PresentFenceIsNotReliable)) {
mStartPropertySetThread = new StartPropertySetThread(false);
} else {
mStartPropertySetThread = new StartPropertySetThread(true);
}
// 执行 StartPropertySetThread,该线程会经过 setProp 触发开机动画,包括设置如下两个Prop
// property_set("service.bootanim.exit", "0"); 复位动画退出标记
// property_set("ctl.start", "bootanim"); 启动开机动画
if (mStartPropertySetThread->Start() != NO_ERROR) {
ALOGE("Run StartPropertySetThread failed!");
}
...
ALOGV("Done initializing");
}
复制代码
init()
方法初始化了不少重要的对象:
app
和sf
两组DispSyncSource
和EventThread
对象
VSYNC
信号的两个消费者:App
和SurfaceFlinger
sf
对应的信号分发逻辑与铺垫知识中的一致,由于是经过mEventQueue->setEventThread()
来进行的关联app
的信号分发逻辑等下细看HWComposer
,并经过registerCallback()
注册HWC2::ComposerCallback
监听EventControlThread
对象,SurfaceFlinger
用这个对象来控制HWC
是否须要产生VSYNC
信号
VSYNC
信号StartPropertySetThread
线程,该线程会经过setProp
的方式触发开机动画SurfaceFlinger::run
run()
方法比较简单:
void SurfaceFlinger::run() {
do {
waitForEvent();
} while (true);
}
复制代码
方法中执行了一个无限循环来调用waitForEvent()
,具体代码以下:
void SurfaceFlinger::waitForEvent() {
mEventQueue->waitMessage();
}
复制代码
waitForEvent()
方法又调用了MessageQueue
对象的waitMessage()
方法进入一个无限循环,这个方法在MessageQueue
部分中已经介绍过就不细讲啦
因此对于
SurfaceFlinger
进程来讲,执行完run()
当前线程就会进入一个无限循环,剩下的业务处理都变成了消息驱动来实现
App
的绘制通知在SurfaceFlinger
的init()
方法中初始化了一个appEventThread
,在接收到VSYNC
信号后,它便会通知到App
去进行绘制操做,咱们看下这个通知流程
onResume()
咱们已经知道,onResume()
方法后才会进行View
的显示,这部分体如今ActivityThread
中的handleResumeActivity()
方法中,代码以下:
public void handleResumeActivity(...) {
...
// TODO Push resumeArgs into the activity for consideration
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
if (r == null) {
// We didn't actually resume the activity, so skipping any follow-up actions.
return;
}
final Activity a = r.activity;
...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
...
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
}
...
}
复制代码
上面performResumeActivity()
会回调应用程序的onResume()
函数。不过本次咱们重点关注的是wm.addView()
方法,最后调用到的是WindowManagerGlobal.java
的addView()
,代码以下:
public void addView(...) {
...
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
...
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
复制代码
重点是初始化了ViewRootImpl
对象,咱们看下ViewRootImpl
中的setView()
方法的调用:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
...
requestLayout();
...
}
}
}
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
复制代码
执行到scheduleTraversals()
方法就引出来一个最重要的类Choreographer
,整个应用布局的渲染依赖这个对象的发动。
在scheduleTraversals()
方法中调用了mChoreographer
对象的postCallback()
方法添加了一个回调对象mTraversalRunnable
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
复制代码
mTraversalRunnable
回调对象的定义以下:
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
复制代码
doTraversal
内部会调用大名鼎鼎的performTraversal()
方法,到这里App
就能够进行measure/layout/draw
三大流程
那么 mTraversalRunnable
对象是在何时调用的呢?
咱们带着疑问,先看下应用是如何接收VSYNC
信号的
Choreographer
类App
要求渲染动画或者更新画面布局时都会用到Choreographer
,接收VSYNC
信号也依赖于Choreographer
在上面的scheduleTraversals()
方法中执行了Choreographer
对象的postCallback()
方法
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
复制代码
这个方法的含义就是应用程序请求VSYNC
信号,接收到VSYNC
信号后执行mTraversalRunnable
回调
那么接下来咱们看下Choreographer
如何接收vsync
信号
DisplayEventReceiver
类应用层能够经过
DisplayEventReceiver
类用来接收vsync
信号,当接收到vsync
信号后,会执行DisplayEventReceiver
对象的onVsync()
方法
DisplayEventReceiver
是在Android
的View
体系中定义的一个抽象类,对外隐藏的,核心定义以下
public abstract class DisplayEventReceiver {
...
// 用来表示 APP 的 VSYNC 信号源
public static final int VSYNC_SOURCE_APP = 0;
public DisplayEventReceiver(Looper looper) {
this(looper, VSYNC_SOURCE_APP);
}
public DisplayEventReceiver(Looper looper, int vsyncSource) {
...
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue,
vsyncSource);
...
}
private static native long nativeInit(WeakReference<DisplayEventReceiver> receiver, MessageQueue messageQueue, int vsyncSource);
private static native void nativeDispose(long receiverPtr);
private static native void nativeScheduleVsync(long receiverPtr);
...
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
}
...
}
复制代码
须要关注的是
native
方法nativeInit()
来进行初始化操做onVsync()
方法的空实现,当接收到VSYNC
信号后便会调用该方法先看下nativeInit()
的实现
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj, jint vsyncSource) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
...
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue, vsyncSource);
status_t status = receiver->initialize();
...
}
复制代码
nativeInit()
方法建立了一个NativeDisplayEventReceiver
对象,并调用了它的initialize()
方法
NativeDisplayEventReceiver
继承了DisplayEventDispatcher
类,那么咱们的重点即是DisplayEventDispatcher
,头文件定义以下:
class DisplayEventDispatcher : public LooperCallback {
public:
DisplayEventDispatcher(const sp<Looper>& looper,
ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
status_t initialize();
...
private:
sp<Looper> mLooper;
DisplayEventReceiver mReceiver;
...
};
复制代码
核心实现以下:
DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
ISurfaceComposer::VsyncSource vsyncSource) :
mLooper(looper), mReceiver(vsyncSource), mWaitingForVsync(false) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
status_t DisplayEventDispatcher::initialize() {
status_t result = mReceiver.initCheck();
...
int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
this, NULL);
if (rc < 0) {
return UNKNOWN_ERROR;
}
return OK;
}
复制代码
在铺垫知识部分已经了解到,若是应用要接收
VSYNC
信号,须要将其添加到对应的EventThread
中,SF
中一共建立了两个
mSFEventThread
是SurfaceFlinger
专用的
- 在
SurfaceFlinger
的init()
中经过mEventQueue->setEventThread()
进行关联setEventThread()
在铺垫部分也介绍过(铺垫内容-消息和事件分发)mEventThread
用来通知App
的
咱们知道mEventQueue->setEventThread()
关联VSYNC
信号的过程主要分为了两步:
对比DisplayEventDispatcher
中咱们会发现
DisplayEventDispatcher
的initialize()
中作了一个mLooper->addFd()
操做
Looper
类的addFd()
方法是将mReceiveFd
添加到epoll
监听列表DisplayEventDispatcher
中包含一个native
层的DisplayEventReceiver
对象mReceiver
native
层的DisplayEventReceiver
便封装了建立链接
的过程,咱们须要关注的是构造方法部分DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != NULL) {
// createDisplayEventConnection 方法便会调用 mEventThread->createEventConnection() 来建立链接
// 而 mEventThread 即是 App 的 VSYNC 分发线程
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
if (mEventConnection != NULL) {
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
}
}
复制代码
到这里,DisplayEventReceiver
便和SurfaceFlinger
中的mEventThread
创建了联系,当VSYNC
信号产生后,SurfaceFlinger
便会经过mEventThread
通知到DisplayEventReceiver
VSYNC 分发过程已经介绍过了,能够看这里
FrameDisplayEventReceiver
类DisplayEventReceiver
是一个抽象类,FrameDisplayEventReceiver
即是这个类的具体实现,在Choreographer
中定义,代码以下:
private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
super(looper, vsyncSource);
}
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
// vsync 信号分发时便会回调到这里
...
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
// 这里发了一个消息,此处并未主动设置 msg.what,默认值应为 0
// 0 对应的数值为 MSG_DO_FRAME
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}
复制代码
上面onVsync
会往消息队列放一个消息,经过下面的FrameHandler
进行处理:
private final class FrameHandler extends Handler {
public FrameHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_FRAME:
doFrame(System.nanoTime(), 0);
break;
case MSG_DO_SCHEDULE_VSYNC:
doScheduleVsync();
break;
case MSG_DO_SCHEDULE_CALLBACK:
doScheduleCallback(msg.arg1);
break;
}
}
}
复制代码
对于MSG_DO_FRAME
消息,会执行doFrame()
方法,关键代码以下:
void doFrame(long frameTimeNanos, int frame) {
...
mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
...
}
复制代码
doFrame()
方法经过doCallbacks()
执行了各类类型的Callback
,分为4类:
CALLBACK_INPUT
: 处理输入事件处理有关CALLBACK_ANIMATION
: 处理Animation
的处理有关CALLBACK_TRAVERSAL
: 处理和UI
等控件绘制有关CALLBACK_COMMIT
: 处理Commit
相关回调须要注意的是CALLBACK_TRAVERSAL
类型的doCallbacks()
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
复制代码
这个方法便会执行前面在scheduleTraversals()
方法中添加的mTraversalRunnable
回调。而因为CALLBACK_INPUT
、CALLBACK_ANIMATION
会修改View
的属性,因此要先于CALLBACK_TRAVERSAL
执行
狡辩ING:刚接手新平台比较忙,致使原本清明节计划学习的章节一直拖到如今,好在磕磕绊绊的学习完了
SurfaceFlinger
这部分涉及的知识不少,很遗憾深刻Android系统(十二)Android图形显示系统
系列也仅仅只是记录一些基础知识。
View
的绘制部分也并未展开学习,考虑到后面的章节,等了解完整个Android
系统知识后再来补充吧(挖坑ING.....)
最后祝各位同窗五一快乐,你们在求知的道路上一块儿加油哟 <( ̄︶ ̄)↗[GO!]
下一篇深刻Android系统(十三)Android的窗口系统