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

Commit 3d3540da authored by Zhuoyao Zhang's avatar Zhuoyao Zhang
Browse files

Revert "Introduce SurfaceFlinger Queued Transaction"

This reverts commit dca14285.

Reason for revert: b/177355824

Bug: 177355824

Change-Id: Idbca13d2040b0d8e96fb7747bf5534f8c3feb08e
parent dca14285
Loading
Loading
Loading
Loading
+169 −172
Original line number Diff line number Diff line
@@ -1914,17 +1914,19 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT

bool SurfaceFlinger::handleMessageTransaction() {
    ATRACE_CALL();

    if (getTransactionFlags(eTransactionFlushNeeded)) {
        flushPendingTransactionQueues();
        flushTransactionQueue();
    }
    uint32_t transactionFlags = peekTransactionFlags();

    bool flushedATransaction = flushTransactionQueues();

    bool runHandleTransaction =
            ((transactionFlags & (~eTransactionFlushNeeded)) != 0) || mForceTraversal;
            (transactionFlags && (transactionFlags != eTransactionFlushNeeded)) ||
            flushedATransaction ||
            mForceTraversal;

    if (runHandleTransaction) {
        handleTransaction(eTransactionMask);
    } else {
        getTransactionFlags(eTransactionFlushNeeded);
    }

    if (transactionFlushNeeded()) {
@@ -2826,6 +2828,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) {
        });
    }

    commitInputWindowCommands();
    commitTransaction();
}

@@ -2866,6 +2869,11 @@ void SurfaceFlinger::updateInputWindowInfo() {
                                                                     : nullptr);
}

void SurfaceFlinger::commitInputWindowCommands() {
    mInputWindowCommands.merge(mPendingInputWindowCommands);
    mPendingInputWindowCommands.clear();
}

void SurfaceFlinger::updateCursorAsync() {
    compositionengine::CompositionRefreshArgs refreshArgs;
    for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
@@ -3229,55 +3237,55 @@ void SurfaceFlinger::setTraversalNeeded() {
    mForceTraversal = true;
}

void SurfaceFlinger::flushPendingTransactionQueues() {
bool SurfaceFlinger::flushTransactionQueues() {
    // to prevent onHandleDestroyed from being called while the lock is held,
    // we must keep a copy of the transactions (specifically the composer
    // states) around outside the scope of the lock
    std::vector<const TransactionState> transactions;
    bool flushedATransaction = false;
    {
        Mutex::Autolock _l(mQueueLock);
        Mutex::Autolock _l(mStateLock);

        auto it = mPendingTransactionQueues.begin();
        while (it != mPendingTransactionQueues.end()) {
        auto it = mTransactionQueues.begin();
        while (it != mTransactionQueues.end()) {
            auto& [applyToken, transactionQueue] = *it;

            while (!transactionQueue.empty()) {
                const auto& transaction = transactionQueue.front();
                if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime,
                                                   transaction.states)) {
                    setTransactionFlags(eTransactionFlushNeeded);
                    break;
                }
                transactions.push_back(transaction);
                applyTransactionState(transaction.frameTimelineVsyncId, transaction.states,
                                      transaction.displays, transaction.flags,
                                      mPendingInputWindowCommands, transaction.desiredPresentTime,
                                      transaction.isAutoTimestamp, transaction.buffer,
                                      transaction.postTime, transaction.privileged,
                                      transaction.hasListenerCallbacks,
                                      transaction.listenerCallbacks, transaction.originPid,
                                      transaction.originUid, transaction.id, /*isMainThread*/ true);
                transactionQueue.pop();
                flushedATransaction = true;
            }

            if (transactionQueue.empty()) {
                it = mPendingTransactionQueues.erase(it);
                mTransactionQueueCV.broadcast();
                it = mTransactionQueues.erase(it);
                mTransactionCV.broadcast();
            } else {
                it = std::next(it, 1);
            }
        }
    }

    {
        Mutex::Autolock _l(mStateLock);
        for (const auto& transaction : transactions) {
            applyTransactionState(transaction.frameTimelineVsyncId, transaction.states,
                                  transaction.displays, transaction.flags, mInputWindowCommands,
                                  transaction.desiredPresentTime, transaction.isAutoTimestamp,
                                  transaction.buffer, transaction.postTime, transaction.privileged,
                                  transaction.hasListenerCallbacks, transaction.listenerCallbacks,
                                  transaction.originPid, transaction.originUid, transaction.id);
        }
    }
    return flushedATransaction;
}

bool SurfaceFlinger::transactionFlushNeeded() {
    Mutex::Autolock _l(mQueueLock);
    return !mPendingTransactionQueues.empty();
    return !mTransactionQueues.empty();
}


bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
                                                   const Vector<ComposerState>& states,
                                                   bool updateTransactionCounters) {
@@ -3299,8 +3307,6 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
        if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
          ready = false;
        }

        Mutex::Autolock _l(mStateLock);
        sp<Layer> layer = nullptr;
        if (s.surface) {
            layer = fromHandleLocked(s.surface).promote();
@@ -3315,6 +3321,7 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
        if (updateTransactionCounters) {
              // See BufferStateLayer::mPendingBufferTransactions
              if (layer) layer->incrementPendingBufferCount();

        }
    }
    return ready;
@@ -3331,28 +3338,27 @@ status_t SurfaceFlinger::setTransactionState(
    const int64_t postTime = systemTime();

    bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
    {
        Mutex::Autolock _l(mQueueLock);

    Mutex::Autolock _l(mStateLock);

    // If its TransactionQueue already has a pending TransactionState or if it is pending
        auto itr = mPendingTransactionQueues.find(applyToken);
    auto itr = mTransactionQueues.find(applyToken);
    // if this is an animation frame, wait until prior animation frame has
    // been applied by SF
    if (flags & eAnimation) {
            while (itr != mPendingTransactionQueues.end() ||
                   (!mTransactionQueue.empty() && mAnimTransactionPending)) {
                status_t err = mTransactionQueueCV.waitRelative(mQueueLock, s2ns(5));
        while (itr != mTransactionQueues.end()) {
            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
            if (CC_UNLIKELY(err != NO_ERROR)) {
                ALOGW_IF(err == TIMED_OUT,
                         "setTransactionState timed out "
                         "waiting for animation frame to apply");
                break;
            }
                itr = mPendingTransactionQueues.find(applyToken);
            itr = mTransactionQueues.find(applyToken);
        }
    }

        const bool pendingTransactions = itr != mPendingTransactionQueues.end();
    const bool pendingTransactions = itr != mTransactionQueues.end();
    // Expected present time is computed and cached on invalidate, so it may be stale.
    if (!pendingTransactions) {
        const auto now = systemTime();
@@ -3367,117 +3373,55 @@ status_t SurfaceFlinger::setTransactionState(
        }
    }

        // TODO(b/159125966): Remove eEarlyWakeup completly as no client should use this flag
        if (flags & eEarlyWakeup) {
            ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
        }

        if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
            ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
            flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
        }

    IPCThreadState* ipc = IPCThreadState::self();
    const int originPid = ipc->getCallingPid();
    const int originUid = ipc->getCallingUid();

    // Call transactionIsReadyToBeApplied first in case we need to incrementPendingBufferCount
    // if the transaction contains a buffer.
        if (!transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states,
                                           true) ||
    if (!transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true) ||
        pendingTransactions) {
            mPendingTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays,
                                                          flags, inputWindowCommands,
                                                          desiredPresentTime, isAutoTimestamp,
                                                          uncacheBuffer, postTime, privileged,
                                                          hasListenerCallbacks, listenerCallbacks,
                                                          originPid, originUid, transactionId);

        mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags,
                                               desiredPresentTime, isAutoTimestamp, uncacheBuffer,
                                               postTime, privileged, hasListenerCallbacks,
                                               listenerCallbacks, originPid, originUid,
                                               transactionId);
        setTransactionFlags(eTransactionFlushNeeded);
        return NO_ERROR;
    }

        mTransactionQueue.emplace_back(frameTimelineVsyncId, states, displays, flags,
                                       inputWindowCommands, desiredPresentTime, isAutoTimestamp,
                                       uncacheBuffer, postTime, privileged, hasListenerCallbacks,
                                       listenerCallbacks, originPid, originUid, transactionId);
    }

    const auto schedule = [](uint32_t flags) {
        if (flags & eEarlyWakeup) return TransactionSchedule::Early;
        if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
        if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
        return TransactionSchedule::Late;
    }(flags);
    setTransactionFlags(eTransactionFlushNeeded, schedule);

    // if this is a synchronous transaction, wait for it to take effect
    // before returning.
    const bool synchronous = flags & eSynchronous;
    const bool syncInput = inputWindowCommands.syncInputWindows;
    if (!synchronous && !syncInput) {
    applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands,
                          desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged,
                          hasListenerCallbacks, listenerCallbacks, originPid, originUid,
                          transactionId, /*isMainThread*/ false);
    return NO_ERROR;
}

    // Handle synchronous cases.
    {
        Mutex::Autolock _l(mStateLock);
        if (synchronous) {
            mTransactionPending = true;
        }
        if (syncInput) {
            mPendingSyncInputWindows = true;
        }
void SurfaceFlinger::applyTransactionState(
        int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
        const Vector<DisplayState>& displays, uint32_t flags,
        const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
        bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime,
        bool privileged, bool hasListenerCallbacks,
        const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
        uint64_t transactionId, bool isMainThread) {
    uint32_t transactionFlags = 0;

        // applyTransactionState can be called by either the main SF thread or by
        // another process through setTransactionState.  While a given process may wish
        // to wait on synchronous transactions, the main SF thread should never
        // be blocked.  Therefore, we only wait if isMainThread is false.
        while (mTransactionPending || mPendingSyncInputWindows) {
    if (flags & eAnimation) {
        // For window updates that are part of an animation we must wait for
        // previous animation "frames" to be handled.
        while (!isMainThread && mAnimTransactionPending) {
            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
            if (CC_UNLIKELY(err != NO_ERROR)) {
                // just in case something goes wrong in SF, return to the
                // called after a few seconds.
                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
                mTransactionPending = false;
                mPendingSyncInputWindows = false;
                // caller after a few seconds.
                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
                        "waiting for previous animation frame");
                mAnimTransactionPending = false;
                break;
            }
        }
    }
    return NO_ERROR;
}

void SurfaceFlinger::flushTransactionQueue() {
    std::vector<TransactionState> transactionQueue;
    {
        Mutex::Autolock _l(mQueueLock);
        if (!mTransactionQueue.empty()) {
            transactionQueue.swap(mTransactionQueue);
        }
        mTransactionQueueCV.broadcast();
    }

    Mutex::Autolock _l(mStateLock);
    for (const auto& t : transactionQueue) {
        applyTransactionState(t.frameTimelineVsyncId, t.states, t.displays, t.flags,
                              t.inputWindowCommands, t.desiredPresentTime, t.isAutoTimestamp,
                              t.buffer, t.postTime, t.privileged, t.hasListenerCallbacks,
                              t.listenerCallbacks, t.originPid, t.originUid, t.id);
    }
}

void SurfaceFlinger::applyTransactionState(int64_t frameTimelineVsyncId,
                                           const Vector<ComposerState>& states,
                                           const Vector<DisplayState>& displays, uint32_t flags,
                                           const InputWindowCommands& inputWindowCommands,
                                           const int64_t desiredPresentTime, bool isAutoTimestamp,
                                           const client_cache_t& uncacheBuffer,
                                           const int64_t postTime, bool privileged,
                                           bool hasListenerCallbacks,
                                           const std::vector<ListenerCallbacks>& listenerCallbacks,
                                           int originPid, int originUid, uint64_t transactionId) {
    uint32_t transactionFlags = 0;

    for (const DisplayState& display : displays) {
        transactionFlags |= setDisplayStateLocked(display);
@@ -3536,25 +3480,80 @@ void SurfaceFlinger::applyTransactionState(int64_t frameTimelineVsyncId,
        transactionFlags = eTransactionNeeded;
    }

    // If we are on the main thread, we are about to preform a traversal. Clear the traversal bit
    // so we don't have to wake up again next frame to preform an uneeded traversal.
    if (isMainThread && (transactionFlags & eTraversalNeeded)) {
        transactionFlags = transactionFlags & (~eTraversalNeeded);
        mForceTraversal = true;
    }

    const auto schedule = [](uint32_t flags) {
        if (flags & eEarlyWakeup) return TransactionSchedule::Early;
        if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
        if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
        return TransactionSchedule::Late;
    }(flags);

    if (transactionFlags) {
        if (mInterceptor->isEnabled()) {
            mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags,
                                          originPid, originUid, transactionId);
        }

        // We are on the main thread, we are about to preform a traversal. Clear the traversal bit
        // so we don't have to wake up again next frame to preform an unnecessary traversal.
        if (transactionFlags & eTraversalNeeded) {
            transactionFlags = transactionFlags & (~eTraversalNeeded);
            mForceTraversal = true;
        // TODO(b/159125966): Remove eEarlyWakeup completly as no client should use this flag
        if (flags & eEarlyWakeup) {
            ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
        }
        if (transactionFlags) {
            setTransactionFlags(transactionFlags);

        if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
            ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
            flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
        }

        // this triggers the transaction
        setTransactionFlags(transactionFlags, schedule);

        if (flags & eAnimation) {
            mAnimTransactionPending = true;
        }

        // if this is a synchronous transaction, wait for it to take effect
        // before returning.
        const bool synchronous = flags & eSynchronous;
        const bool syncInput = inputWindowCommands.syncInputWindows;
        if (!synchronous && !syncInput) {
            return;
        }

        if (synchronous) {
            mTransactionPending = true;
        }
        if (syncInput) {
            mPendingSyncInputWindows = true;
        }


        // applyTransactionState can be called by either the main SF thread or by
        // another process through setTransactionState.  While a given process may wish
        // to wait on synchronous transactions, the main SF thread should never
        // be blocked.  Therefore, we only wait if isMainThread is false.
        while (!isMainThread && (mTransactionPending || mPendingSyncInputWindows)) {
            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
            if (CC_UNLIKELY(err != NO_ERROR)) {
                // just in case something goes wrong in SF, return to the
                // called after a few seconds.
                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
                mTransactionPending = false;
                mPendingSyncInputWindows = false;
                break;
            }
        }
    } else {
        // Update VsyncModulator state machine even if transaction is not needed.
        if (schedule == TransactionSchedule::EarlyStart ||
            schedule == TransactionSchedule::EarlyEnd) {
            modulateVsync(&VsyncModulator::setTransactionSchedule, schedule);
        }
    }
}

@@ -3946,7 +3945,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(
}

uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
    bool hasChanges = mInputWindowCommands.merge(inputWindowCommands);
    bool hasChanges = mPendingInputWindowCommands.merge(inputWindowCommands);
    return hasChanges ? eTraversalNeeded : 0;
}

@@ -4211,11 +4210,9 @@ void SurfaceFlinger::onInitializeDisplays() {
    d.width = 0;
    d.height = 0;
    displays.add(d);

    // This called on the main thread, apply it directly.
    applyTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0,
                          mInputWindowCommands, systemTime(), true, {}, systemTime(), true, false,
                          {}, getpid(), getuid(), 0 /* Undefined transactionId */);
    setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr,
                        mPendingInputWindowCommands, systemTime(), true, {}, false, {},
                        0 /* Undefined transactionId */);

    setPowerModeInternal(display, hal::PowerMode::ON);
    const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
@@ -5392,7 +5389,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r

void SurfaceFlinger::repaintEverything() {
    mRepaintEverything = true;
    setTransactionFlags(eTransactionNeeded);
    signalTransaction();
}

void SurfaceFlinger::repaintEverythingForHWC() {
+9 −16
Original line number Diff line number Diff line
@@ -434,16 +434,15 @@ private:
    struct TransactionState {
        TransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& composerStates,
                         const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
                         const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
                         bool isAutoTimestamp, const client_cache_t& uncacheBuffer,
                         int64_t postTime, bool privileged, bool hasListenerCallbacks,
                         int64_t desiredPresentTime, bool isAutoTimestamp,
                         const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged,
                         bool hasListenerCallbacks,
                         std::vector<ListenerCallbacks> listenerCallbacks, int originPid,
                         int originUid, uint64_t transactionId)
              : frameTimelineVsyncId(frameTimelineVsyncId),
                states(composerStates),
                displays(displayStates),
                flags(transactionFlags),
                inputWindowCommands(inputWindowCommands),
                desiredPresentTime(desiredPresentTime),
                isAutoTimestamp(isAutoTimestamp),
                buffer(uncacheBuffer),
@@ -459,7 +458,6 @@ private:
        Vector<ComposerState> states;
        Vector<DisplayState> displays;
        uint32_t flags;
        InputWindowCommands inputWindowCommands;
        const int64_t desiredPresentTime;
        const bool isAutoTimestamp;
        client_cache_t buffer;
@@ -725,7 +723,6 @@ private:
    /*
     * Transactions
     */
    void flushTransactionQueue();
    void applyTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
                               const Vector<DisplayState>& displays, uint32_t flags,
                               const InputWindowCommands& inputWindowCommands,
@@ -733,12 +730,10 @@ private:
                               const client_cache_t& uncacheBuffer, const int64_t postTime,
                               bool privileged, bool hasListenerCallbacks,
                               const std::vector<ListenerCallbacks>& listenerCallbacks,
                               int originPid, int originUid, uint64_t transactionId)
            REQUIRES(mStateLock);
                               int originPid, int originUid, uint64_t transactionId,
                               bool isMainThread = false) REQUIRES(mStateLock);
    // Returns true if at least one transaction was flushed
    bool flushTransactionQueues();
    // flush pending transaction that was presented after desiredPresentTime.
    void flushPendingTransactionQueues();
    // Returns true if there is at least one transaction that needs to be flushed
    bool transactionFlushNeeded();
    uint32_t getTransactionFlags(uint32_t flags);
@@ -756,7 +751,7 @@ private:
    void commitOffscreenLayers();
    bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
                                       const Vector<ComposerState>& states,
                                       bool updateTransactionCounters = false);
                                       bool updateTransactionCounters = false) REQUIRES(mStateLock);
    uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
    uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
            REQUIRES(mStateLock);
@@ -1173,11 +1168,8 @@ private:
    uint32_t mTexturePoolSize = 0;
    std::vector<uint32_t> mTexturePool;

    mutable Mutex mQueueLock;
    Condition mTransactionQueueCV;
    std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash>
            mPendingTransactionQueues GUARDED_BY(mQueueLock);
    std::vector<TransactionState> mTransactionQueue GUARDED_BY(mQueueLock);
    std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash> mTransactionQueues;

    /*
     * Feature prototyping
     */
@@ -1254,6 +1246,7 @@ private:
    const float mEmulatedDisplayDensity;

    sp<os::IInputFlinger> mInputFlinger;
    InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock);
    // Should only be accessed by the main thread.
    InputWindowCommands mInputWindowCommands;

+0 −3
Original line number Diff line number Diff line
@@ -68,9 +68,6 @@ public:
                                       Rect(displayState.layerStackSpaceRect), Rect(resolution));
                t.apply();
                SurfaceComposerClient::Transaction().apply(true);
                // wait for 3 vsyncs to ensure the buffer is latched.
                usleep(static_cast<int32_t>(1e6 / displayConfig.refreshRate) * 3);

                BufferItem item;
                itemConsumer->acquireBuffer(&item, 0, true);
                auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer);
+2 −2
Original line number Diff line number Diff line
@@ -365,7 +365,7 @@ public:
        return mFlinger->SurfaceFlinger::getDisplayNativePrimaries(displayToken, primaries);
    }

    auto& getPendingTransactionQueue() { return mFlinger->mPendingTransactionQueues; }
    auto& getTransactionQueue() { return mFlinger->mTransactionQueues; }

    auto setTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
                             const Vector<DisplayState>& displays, uint32_t flags,
@@ -381,7 +381,7 @@ public:
                                             listenerCallbacks, transactionId);
    }

    auto flushPendingTransactionQueues() { return mFlinger->flushPendingTransactionQueues(); };
    auto flushTransactionQueues() { return mFlinger->flushTransactionQueues(); };

    auto onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
        return mFlinger->onTransact(code, data, reply, flags);
+10 −10

File changed.

Preview size limit exceeded, changes collapsed.