天天看點

surfaceflinger 程序啟動surfaceflinger程序

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消息中會詳細論述。

繼續閱讀