Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9339952b authored by Steven Moreland's avatar Steven Moreland
Browse files

surfaceflinger: fix race condition

surfaceflinger only has one thread.

main thread is:
a). startHidlServices
b). do a getService
c). getService receives notification on binder thread and returns
d). binder ServiceManager register SF service

Then, started by a).
hwbinder thread is (DisplayService's, when it receives a transaction):
e). binder ServiceManager get SF service ( (d) must happen first! )

Normally, (e) never happens because nothing calls into DisplayService
until later. However, on a particular QCOM device (b/80061790),
surfaceflinger restarts at just the right time that this sequence happens:
(a) (b) (e)

then (c) is blocked since (e) is on a binder thread).

Test: QCOM device no longer enters this deadlock
Test: boot up on Pixel device
Test: (sanity) check to make sure surface flinger has one hwbinder thread
Test: (sanity) make sure Pixel device surface flinger doesn't register an
    allocator when it isn't supposed to.

As a follow-up, the return values from these various services will be
checked.

Bug: 80061790
Change-Id: I254d70951ee9508790c940240bcd1da5af746dd3
parent c61c0c11
Loading
Loading
Loading
Loading
+17 −19
Original line number Diff line number Diff line
@@ -35,6 +35,13 @@
using namespace android;

static status_t startGraphicsAllocatorService() {
    using android::hardware::configstore::getBool;
    using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
    if (!getBool<ISurfaceFlingerConfigs,
            &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
        return OK;
    }

    using android::hardware::graphics::allocator::V2_0::IAllocator;

    status_t result =
@@ -47,27 +54,12 @@ static status_t startGraphicsAllocatorService() {
    return OK;
}

static status_t startHidlServices() {
static status_t startDisplayService() {
    using android::frameworks::displayservice::V1_0::implementation::DisplayService;
    using android::frameworks::displayservice::V1_0::IDisplayService;
    using android::hardware::configstore::getBool;
    using android::hardware::configstore::getBool;
    using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
    hardware::configureRpcThreadpool(1 /* maxThreads */,
            false /* callerWillJoin */);

    status_t err;

    if (getBool<ISurfaceFlingerConfigs,
            &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
        err = startGraphicsAllocatorService();
        if (err != OK) {
           return err;
        }
    }

    sp<IDisplayService> displayservice = new DisplayService();
    err = displayservice->registerAsService();
    status_t err = displayservice->registerAsService();

    if (err != OK) {
        ALOGE("Could not register IDisplayService service.");
@@ -77,9 +69,13 @@ static status_t startHidlServices() {
}

int main(int, char**) {
    startHidlServices();

    signal(SIGPIPE, SIG_IGN);

    hardware::configureRpcThreadpool(1 /* maxThreads */,
            false /* callerWillJoin */);

    startGraphicsAllocatorService();

    // When SF is launched in its own process, limit the number of
    // binder threads to 4.
    ProcessState::self()->setThreadPoolMaxThreadCount(4);
@@ -112,6 +108,8 @@ int main(int, char**) {
    sp<GpuService> gpuservice = new GpuService();
    sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);

    startDisplayService(); // dependency on SF getting registered above

    struct sched_param param = {0};
    param.sched_priority = 2;
    if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {