[Android Meditation Path] SurfaceFlinger launch process

The Path of Android Meditation

An overview of

SurfaceFlinger is a system service, so its startup mode is the same as other system services. In Android, there are two startup modes for system services.

  1. Started by ServiceManager
  2. The configuration is started separately in the RC file

For SurfaceFlinger, it takes the second approach.

Of course, the system service startup principle will not be in-depth here, we need to focus on the process of SurfaceFlinger startup. Android starts the SurfaceFlinger service using the surfaceFlinger. Rc file. SurfaceFlinger source file configuration in the frameworks/native/services/SurfaceFlinger/Android. The bp file. The main function in the main_surfaceFlinger. CPP file will be executed as specified in the android. bp file. So let’s start with the first main function that SurfaceFlinger launches.

Two main_surfaceflinger

2.1 main_surfaceflinger: main

int main(int.char* *) {
    signal(SIGPIPE, SIG_IGN);

    // Set the maximum number of hwBinder threads.
    hardware::configureRpcThreadpool(1 /* maxThreads */.false /* callerWillJoin */);

    // // starts the Graphics Allocator service, which is used for GraphicBuffer allocation
    startGraphicsAllocatorService(a);// Now the SF process has 4 Binder threads
    ProcessState::self() - >setThreadPoolMaxThreadCount(4);

    // Start the thread pool
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool(a);// Create the SF object
    sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger(a);// Set the thread priority
    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);

    // Set scheduling policies and priorities
    set_sched_policy(0, SP_FOREGROUND);

    if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);

    // initialize SF
    flinger->init(a);// Publish SF system services to ServiceManager
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);

    / / start DisplayService
    startDisplayService(a);struct sched_param param = {0};
    param.sched_priority = 2;
    if (sched_setscheduler(0, SCHED_FIFO, &param) ! =0) {
        ALOGE("Couldn't set SCHED_FIFO");
    }

    // Start the SF thread
    flinger->run(a);return 0;
}
Copy the code

The logic in main is longer, and can be easily broken down into the following steps

  1. Set the maximum number of threads in hwBinder to 4. Hwbinder is actually a binder. If you look at the early Android code, hwBinder is not hwBinder. Hwbinder, VNdbinder, we’ll just say binder
  2. Start the Graphics Allocator service
  3. Through surfaceflinger: : create surfaceflinger createSurfaceFlinger
  4. Initialize SurfaceFlinger
  5. Publish the SurfaceFlinger service to the ServiceManager
  6. Start the DisplayService
  7. Call SurfaceFlinger’s run method

There are a lot of important points about SurfaceFlinger, so let’s briefly analyze its startup process

During SurfaceFlinger startup, the main thing to do is start the SurfaceFlinger system service, publish it to the ServiceManager, and start its own Binder threads. Of course, along the way, some of the other services SurfaceFlinger relies on are also started. For example, Graphics Allocator is a very important service that we’ll cover separately later, but these services are not the focus of this article for now.

There are really only two lines of code that are involved in starting and initializing SurfaceFlinger, and you just need to focus on them

// 1. Create SurfaceFlinger object
sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
// 2. Call SurfaceFlinger's initialization function
flinger->init();
Copy the code

2.2 Definition of SurfaceFlinger

Before looking at two lines of code, let’s look at the definition of the SurfaceFlinger class:

[frameworks/native/services/surfaceflinger/SurfaceFlinger.h]
class SurfaceFlinger : public BnSurfaceComposer,
                       public PriorityDumper,
                       public ClientCache::ErasedRecipient,
                       private IBinder::DeathRecipient,
                       private HWC2::ComposerCallback {
Copy the code
  • The SurfaceFlinger class inherits BnSurfaceComposer, which is an implementation class for Binder communication. The SurfaceFlinger class inherits BnSurfaceComposer, which is an implementation class for Binder communication
  • Then you see that it implements a HWC2 hardware-specific callback that handles vsync-specific logic

Of course, we don’t need to remember all the classes that SurfaceFlinger implements, but if we don’t, we can look back.

Three SurfaceFlinger. CPP

3.1 SurfaceFlingerFactory

The SurfaceFlinger is created using a factory class, SurfaceFlingerFactory, which is essentially the SurfaceFlinger constructor called, taking the factory itself.

sp<SurfaceFlinger> createSurfaceFlinger(a) {...return new SurfaceFlinger(factory);
}
Copy the code

This passes the SurfaceFlingerFactory object into the SurfaceFlinger constructor, which will be used when SurfaceFlingerFactory creates other objects.

3.2 SurfaceFlinger’s constructor

The SurfaceFlinger constructor is relatively simple. It just initializes some member variables. It creates a bunch of dependent objects from the SurfaceFlingerFactory object. We’ll do that later when we use it.

[frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
      : mFactory(factory),
        mPhaseOffsets(mFactory.createPhaseOffsets()),
        mInterceptor(mFactory.createSurfaceInterceptor(this)),
        mTimeStats(mFactory.createTimeStats()),
        mEventQueue(mFactory.createMessageQueue()),
        mCompositionEngine(mFactory.createCompositionEngine() {}Copy the code

3.3 SurfaceFlinger: : init

Next comes the init function called in the main function, which is SurfaceFlinger’s primary initialization

[frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::init(a) {...// 1 Start EventThread (App EventThread and SF EventThread)
	/ / getFactory SurfaceFlingerDefaultFactory is ()
    mAppConnectionHandle =
            mScheduler->createConnection("app", mVsyncModulator.getOffsets().app,
                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                         resyncCallback,
                                         impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle =
            mScheduler->createConnection("sf", mVsyncModulator.getOffsets().sf,
                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                         resyncCallback, [this] (nsecs_ttimestamp) { mInterceptor->saveVSyncEvent(timestamp); }); .// 2 Initializes EGL
	2.1 EGL Configuration
    int32_t renderEngineFeature = 0;
    renderEngineFeature |= (useColorManagement ?
                            renderengine::RenderEngine::USE_COLOR_MANAGEMENT : 0);
    renderEngineFeature |= (useContextPriority ?
                            renderengine::RenderEngine::USE_HIGH_PRIORITY_CONTEXT : 0);
    renderEngineFeature |=
            (enable_protected_contents(false)? renderengine::RenderEngine::ENABLE_PROTECTED_CONTEXT :0);

    // 2.2 EGL creation
    mCompositionEngine->setRenderEngine(
        renderengine::RenderEngine::create(static_cast<int32_t>(defaultCompositionPixelFormat),
                                               renderEngineFeature, maxFrameBufferAcquiredBuffers));

    // 2.3 Creating HWComposer
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName));
    mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId);
    //3 Handle the hot swap event
    processDisplayHotplugEventsLocked();
    const auto display = getDefaultDisplayDeviceLocked();

	// If VR Flinger is enabled, the value is false
    if (useVrFlinger) {
        auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
            postMessageAsync(new LambdaMessage([=] {
                ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
                mVrFlingerRequestsDisplay = requestDisplay;
                signalTransaction();
            }));
        };
        mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(),
                                            getHwComposer()
                                                    .fromPhysicalDisplayId(*display->getId())
                                                    .value_or(0),
                                            vrFlingerRequestDisplayCallback);
    }

    mDrawingState = mCurrentState;

    // 4 Initialize the event
    initializeDisplays();

    getRenderEngine().primeCache();

    const boolpresentFenceReliable = ! getHwComposer().hasCapability(HWC2::Capability::PresentFenceIsNotReliable);//5 Boot animationmStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable); . }Copy the code

There are a lot of other things that are relevant here, such as EventQueue mechanism in SurfaceFlinger, Vsync mechanism, hardware Vsync and software Vsync callback mechanism, and so on. These mechanisms are very complicated, so let’s document them for the moment. Each mechanism will be explained separately later. We’re going to assume for the moment that we know this, that we’ve learned the main process.

There is a lot of logic in the init function, so here is a brief summary:

  1. Create a Scheduler
  2. Construct a callback function, ResyncCallback
  3. Create two connection handlers, ConnectionHandles,
    1. The first step is to create two eventThreads, namely app EventThread and SF EventThread
    2. There is a VSync callback in EventThread
    3. There is a Thread in EventThread, which is an infinite loop that listens for VSync events, consumes distribution, and waits in the absence of events
    4. The EventThread is then connected, calling the createConnectionInternal in the Scheduler
  4. Inject the EventThreadConnection corresponding to mSfConnectionHandle into mEventQueue
  5. Set Vsync monitoring and area sampling
  6. Initialize EGL(configure, create)
  7. Procedure Handle hot swap events
  8. Initialization event
  9. Boot animation

3.4 Other operations in SurfaceFlinger initialization

There’s actually some initialization that’s done in addition to the init function. Binder, for example, calls onFirstRef when SurfaceFlinger generates a strong pointer for the first time. Publishing system services through ServiceManager calls binderDied functions through Binder’s death proxy, which are also listed here.

void SurfaceFlinger::onFirstRef(a)
{
    // Initialize the message queue
    mEventQueue->init(this);
}

void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
{

    // Reinitialize the display device
    initializeDisplays(a);// Start the Boot animation
    startBootAnim(a); }Copy the code

Four summarizes

The startup process of SurfaceFlinger is still relatively simple in general, but there are many other mechanisms involved in it. If we go into all of them, we will easily get caught in the sea of source code and eventually forget our original purpose. Therefore, in this article, we will only learn about the startup process of SurfaceFlinger. As for the mechanism of SurfaceFlinger involved, we first assume that we have mastered it, and then make a single point breakthrough for the mechanism after we have mastered the overall working process of SurfaceFlinger, and finally bring these mechanisms into the overall process.