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

Commit 90f669f2 authored by Chia-I Wu's avatar Chia-I Wu
Browse files

surfaceflinger: make vsync injection more robust

There are more issues than I expected :)

 - no lock to synchronize enable/disable and injection
 - Every time injection is diabled and enabled, a new EventThread is
   created
 - mCallback might be nullptr
 - ENABLE_VSYNC_INJECTIONS/INJECT_VSYNC should require special
   permission
 - MessageQueue::setEventThread must be called from the main thread
 - MessageQueue::setEventThread does not handle EventThread switch
   well

Bug: 65483324
Test: manual
Change-Id: I7d7b98d1f57afc64af0f2065a9bc7c8ad004ca9f
parent a6c44309
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -91,6 +91,14 @@ void MessageQueue::init(const sp<SurfaceFlinger>& flinger)


void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
{
    if (mEventThread == eventThread) {
        return;
    }

    if (mEventTube.getFd() >= 0) {
        mLooper->removeFd(mEventTube.getFd());
    }

    mEventThread = eventThread;
    mEventThread = eventThread;
    mEvents = eventThread->createEventConnection();
    mEvents = eventThread->createEventConnection();
    mEvents->stealReceiveChannel(&mEventTube);
    mEvents->stealReceiveChannel(&mEventTube);
+26 −16
Original line number Original line Diff line number Diff line
@@ -570,8 +570,10 @@ public:


    virtual void onInjectSyncEvent(nsecs_t when) {
    virtual void onInjectSyncEvent(nsecs_t when) {
        std::lock_guard<std::mutex> lock(mCallbackMutex);
        std::lock_guard<std::mutex> lock(mCallbackMutex);
        if (mCallback) {
            mCallback->onVSyncEvent(when);
            mCallback->onVSyncEvent(when);
        }
        }
    }


    virtual void setVSyncEnabled(bool) {}
    virtual void setVSyncEnabled(bool) {}
    virtual void setPhaseOffset(nsecs_t) {}
    virtual void setPhaseOffset(nsecs_t) {}
@@ -1066,12 +1068,14 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& display,
}
}


status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
    if (enable == mInjectVSyncs) {
    sp<LambdaMessage> enableVSyncInjections = new LambdaMessage([&]() {
        return NO_ERROR;
        Mutex::Autolock _l(mStateLock);

        if (mInjectVSyncs == enable) {
            return;
        }
        }


        if (enable) {
        if (enable) {
        mInjectVSyncs = enable;
            ALOGV("VSync Injections enabled");
            ALOGV("VSync Injections enabled");
            if (mVSyncInjector.get() == nullptr) {
            if (mVSyncInjector.get() == nullptr) {
                mVSyncInjector = new InjectVSyncSource();
                mVSyncInjector = new InjectVSyncSource();
@@ -1079,15 +1083,19 @@ status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
            }
            }
            mEventQueue.setEventThread(mInjectorEventThread);
            mEventQueue.setEventThread(mInjectorEventThread);
        } else {
        } else {
        mInjectVSyncs = enable;
            ALOGV("VSync Injections disabled");
            ALOGV("VSync Injections disabled");
            mEventQueue.setEventThread(mSFEventThread);
            mEventQueue.setEventThread(mSFEventThread);
        mVSyncInjector.clear();
        }
        }

        mInjectVSyncs = enable;
    });
    postMessageSync(enableVSyncInjections);
    return NO_ERROR;
    return NO_ERROR;
}
}


status_t SurfaceFlinger::injectVSync(nsecs_t when) {
status_t SurfaceFlinger::injectVSync(nsecs_t when) {
    Mutex::Autolock _l(mStateLock);

    if (!mInjectVSyncs) {
    if (!mInjectVSyncs) {
        ALOGE("VSync Injections not enabled");
        ALOGE("VSync Injections not enabled");
        return BAD_VALUE;
        return BAD_VALUE;
@@ -3983,6 +3991,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
        case GET_ANIMATION_FRAME_STATS:
        case GET_ANIMATION_FRAME_STATS:
        case SET_POWER_MODE:
        case SET_POWER_MODE:
        case GET_HDR_CAPABILITIES:
        case GET_HDR_CAPABILITIES:
        case ENABLE_VSYNC_INJECTIONS:
        case INJECT_VSYNC:
        {
        {
            // codes that require permission check
            // codes that require permission check
            IPCThreadState* ipc = IPCThreadState::self();
            IPCThreadState* ipc = IPCThreadState::self();