surfaceflinger程序
surfaceflinger是一個守護程序,開機啟動。
surfaceflinger代碼的路徑如下,
frameworks\native\services\surfaceflinger
在android 8.1系統中, surfaceflinger程序對應的配置不是在init.rc中,而是在surfaceflinger.rc中,如下,
service surfaceflinger /system/bin/surfaceflinger
class core animation
user system
group graphics drmrpc readproc
onrestart restart zygote
writepid /dev/stune/foreground/tasks
socket pdx/system/vr/display/client
stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
socket pdx/system/vr/display/manager
stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
socket pdx/system/vr/display/vsync
stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
需要注意的是,這裡面有3個socket,用于跨程序通信。
Surfaceflinger程序的入口方法為main_surfaceflinger.cpp的main方法,主要邏輯如下,
1,啟動服務,
startHidlServices();
signal(SIGPIPE, SIG_IGN); //當對端(用戶端/服務端)的socket關閉時,防止程序退出。
2,設定最大線程池個數并啟動線程池,
ProcessState::self()->setThreadPoolMaxThreadCount(4);//線程池個數為4
// start the thread pool
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
3,擷取SurfaceFlinger服務對象,設定優先權以及線程的優先級,最後初始化SurfaceFlinger服務,
sp<SurfaceFlinger> flinger = DisplayUtils::getInstance()->getSFInstance();
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
set_sched_policy(0, SP_FOREGROUND);
if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
flinger->init(); //初始化
4,添加系統服務,
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
// publish GpuService
sp<GpuService> gpuservice = new GpuService();
sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
首先調用defaultServiceManager方法擷取ServiceManager代理對象,這個方法在守護程序中的C/C++ 很常見,和Java層的擷取ServiceManager完全對應。
将SurfaceFlinger 的GpuService 服務分别添加到系統中,這樣,其他程序才可以調用方法擷取這2個服務的代理對象。
SurfaceFlinger.h的getServiceName方法如下,
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
}
GpuService.cpp的SERVICE_NAME如下,
const char* const GpuService::SERVICE_NAME = "gpu";
是以,其他程序通過SurfaceFlinger 關鍵字可以擷取SurfaceFlinger服務對象;
通過gpu 擷取GpuService對象。
5,設定排程政策,
struct sched_param param = {0};
param.sched_priority = 2;
if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO");
}
6,運作SurfaceFlinger服務,
flinger->run();
在此,主要看SurfaceFlinger有關的方法,主要是SurfaceFlinger的擷取,初始化方法init(),以及最後的run方法。
擷取SurfaceFlinger對象
擷取SurfaceFlinger的代碼如下,
sp<SurfaceFlinger> flinger = DisplayUtils::getInstance()->getSFInstance();
DisplayUtils的是一個單例, getInstance方法如下,
if (sDisplayUtils == NULL) {
sDisplayUtils = new DisplayUtils();
}
return sDisplayUtils;
DisplayUtils的構造方法如下,
DisplayUtils::DisplayUtils() { // sUseExtendedImpls 一般為false
#ifdef QTI_BSP
sUseExtendedImpls = true;
#endif
}
DisplayUtils的getSFInstance方法如下,
if (sUseExtendedImpls) {
return new ExSurfaceFlinger();
} else {
return new SurfaceFlinger();
}
在此,僅論述SurfaceFlinger這一種情況。對于具體的高通msm8909晶片, 根據宏定義-TARGET_USES_HWC2,相應的surfaceflinger對應的檔案是SurfaceFlinger_hwc1.cpp, 實際HWComposer加載的檔案是HWComposer_hwc1.cpp,SurfaceFlinger的構造方法主要是初始化一些成員變量,但是調用了DispSync的init方法對DispSync進行初始化,
mPrimaryDispSync.init(hasSyncFramework, dispSyncPresentTimeOffset);
這部分後面會詳細論述。
在SurfaceFlinger的其他方法之前,onFirstRef方法會被調用, onFirstRef方法如下,
mEventQueue.init(this);
在SurfaceFlinger.h中, mEventQueue如下,
mutable MessageQueue mEventQueue;
mEventQueue是MessageQueue對象, init方法如下,
mFlinger = flinger; //指向SurfaceFlinger 對象
mLooper = new Looper(true);
mHandler = new Handler(*this);
構造Looper 和 Handler對象。
init方法
SurfaceFlinger的init方法主要邏輯如下,
1, 初始化OpenGL ES圖形庫
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(mEGLDisplay, NULL, NULL);
2,建立同步信号線程并設定排程政策, 監聽和處理SurfaceFlinger中的事件。
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc, *this, false);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
// set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
param.sched_priority = 2;
if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
}
if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for EventThread");
}
3,構造顯示裝置抽象類,和顯示裝置互動。
mHwc.reset(new HWComposer(this,
*static_cast<HWComposer::EventHandler *>(this)));
mHwc->registerCallback(this, mComposerSequenceId);
4,初始化顯示裝置
initializeDisplays();
5,設定同步信号周期,頻率為60Hz,
if (mHwc->initCheck() != NO_ERROR) {
mPrimaryDispSync.setPeriod(16666667);
}
run方法
SurfaceFlinger的run方法如下,
do {
waitForEvent();
} while (true);
waitForEvent方法如下,
mEventQueue.waitMessage();
MessageQueue的waitMessage方法也是一個do – while循環,裡面邏輯如下,
1,阻塞消息,
IPCThreadState::self()->flushCommands();
int32_t ret = mLooper->pollOnce(-1);
flushCommands方法主要是對binder驅動進行互動, 清理binder
pollOnce是消息機制,主要調用了epoll_wait函數,會阻塞,阻塞完了會分發消息隊列中的消息。這裡的消息隻有自己在Handler中發的消息,還有在setEventThread中自己添加的消息。
2,處理不同消息,
switch (ret) {
case Looper::POLL_WAKE:
case Looper::POLL_CALLBACK:
continue;
•••
在init方法中,構造同步信号時調用了MessageQueue的setEventThread方法,
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
MessageQueue的setEventThread方法如下,
mEventThread = eventThread;
mEvents = eventThread->createEventConnection();
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
調用EventThread的createEventConnection來建立一個連接配接, 用來分發VSync消息。在VSync消息中會詳細論述。