surfaceflinger 进程启动
Posted Achillisjack
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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消息中会详细论述。
以上是关于surfaceflinger 进程启动的主要内容,如果未能解决你的问题,请参考以下文章