SurfaceFlinger10-Transaction在sf进程中的提交过程

前言

本文基于Android 14源码分析整理

在《SurfaceFlinger03-Transaction基础》中,对Transaction的基础原理和使用方式进行了简单总结。当业务进程设置好Transaction所携带数据后,通过Transaction::apply()方法就可以将该Transaction提交给surfaceflinger进程。

surfaceflinger进程收到来自客户端的Transaction后,会先以TransactionState的形式添加到列表中进行保存,然后在下一帧提交时,在主线程中以Transaction设置的Token为Key,将相同token的Transaction放在同一队列中进行归类,然后进行状态筛选,如果筛选通过,则应用到这一帧的提交于合成过程,否则会一直放在队列中,直到条件满足。

本篇文章中,对Transaction的提交流程(flushTransaction)进行汇总,包括Transaction的保存、筛选、以及其中涉及到的一些类和系统机制。

一、TransactionFilter设置

sf在每帧提交过程中,TransactionFilter用于从Transaction待提交队列中筛选状态已经准备完成的Transaction。在sf进程启动初始化过程中时,便会完成TransactionFilter的设置:

cpp 复制代码
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
    // 设置TransactionFilter
    addTransactionReadyFilters();
    ......
}

void SurfaceFlinger::addTransactionReadyFilters() {
    // 添加TransactionFilter函数
    mTransactionHandler.addTransactionReadyFilter(
            std::bind(&SurfaceFlinger::transactionReadyTimelineCheck, this, std::placeholders::_1));
    mTransactionHandler.addTransactionReadyFilter(
            std::bind(&SurfaceFlinger::transactionReadyBufferCheck, this, std::placeholders::_1));
}


// frameworks/native/services/surfaceflinger/FrontEnd/TransactionHandler.cpp

void TransactionHandler::addTransactionReadyFilter(TransactionFilter&& filter) {
    // 将TransactionFilter添加到mTransactionReadyFilters列表中
    mTransactionReadyFilters.emplace_back(std::move(filter));
}

以上方法中,通过mTransactionHandler设置了两个TransactionFilter。

TransactionFilter实际类型为一个函数接口:

cpp 复制代码
// frameworks/native/services/surfaceflinger/FrontEnd/TransactionHandler.h

using TransactionFilter = std::function<TransactionReadiness(const TransactionFlushState&)>;
  • SurfaceFlinger::transactionReadyTimelineCheck():筛选Transaction所携带的指定时间戳是否满足在当前帧进行提交与合成;
  • SurfaceFlinger::transactionReadyBufferCheck():筛选Transaction所携带的GraphicBuffer是否满足在当前帧进行提交并参与合成。

以上两个TransactionFilter的实现在后续进行说明。

二、Transaction的入队保存

Client端发起Transaction::apply()操作后,会发起向surfaceflinger进程的调用,sf进程中SurfaceFlinger::setTransactionState()方法将会得到执行,这个方法中,会将Transaction携带的所有属性封装在TransactionState对象中,并添加到指定列表中进行保存:

cpp 复制代码
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

status_t SurfaceFlinger::setTransactionState(
        const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states,
        const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
        InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp,
        const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks,
        const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId,
        const std::vector<uint64_t>& mergedTransactionIds) {

    ......
    // sf中收到Transaction时间点
    const int64_t postTime = systemTime();

    // 初始化TransactionState
    TransactionState state{frameTimelineInfo,
                           resolvedStates,
                           displays,
                           flags,
                           applyToken,
                           std::move(inputWindowCommands),
                           desiredPresentTime,
                           isAutoTimestamp,
                           std::move(uncacheBufferIds),
                           postTime,
                           hasListenerCallbacks,
                           listenerCallbacks,
                           originPid,
                           originUid,
                           transactionId,
                           mergedTransactionIds};

    ......
    
    // 将TransactionState添加到mTransactionHandler中的定义队列中
    mTransactionHandler.queueTransaction(std::move(state));
    setTransactionFlags(eTransactionFlushNeeded, schedule, applyToken, frameHint);
    return NO_ERROR;
}

TransactionState代表一个Transaction对象一次apply()时所有携带属性的封装,包括Layer状态、Buffer状态、Display状态、回调监听等信息。

TransactionHandler类专门用于进行TransactionState的各类操作,比如对TransactionState进行入队、筛选、统计等操作。

通过TransactionHandler::queueTransaction()将TransactionState入队保存:

cpp 复制代码
// frameworks/native/services/surfaceflinger/FrontEnd/TransactionHandler.cpp

void TransactionHandler::queueTransaction(TransactionState&& state) {
    // 将TransactionState对象添加到mLocklessTransactionQueue队列中
    mLocklessTransactionQueue.push(std::move(state));
    // 表示待提交Transaction的个数
    mPendingTransactionCount.fetch_add(1);
}

以上方法中,将TransactionState对象保存在了mLocklessTransactionQueue中,在主线程开始筛选时,会将同一个token的TransactionState放在一个队列中。

三、Transaction的筛选过程

sf主线程开始提交流程后,会从Transaction队列中获取符合条件的Transaction并应用于合成过程。

筛选流程从TransactionHandler::flushTransactions()方法开始:

cpp 复制代码
// frameworks/native/services/surfaceflinger/FrontEnd/TransactionHandler.cpp

std::vector<TransactionState> TransactionHandler::flushTransactions() {
    // 从mLocklessTransactionQueue中移动到mPendingTransactionQueues中
    // 同多个Transaction中,以相同的token为键值拿出来重新排列
    while (!mLocklessTransactionQueue.isEmpty()) {
        auto maybeTransaction = mLocklessTransactionQueue.pop();
        if (!maybeTransaction.has_value()) {
            break;
        }
        auto transaction = maybeTransaction.value();
        // 一个Map,key为Transaction token, 值为TransactionState对象
        mPendingTransactionQueues[transaction.applyToken].emplace(std::move(transaction));
    }

    // Collect transaction that are ready to be applied.
    // flush过程中挑选符合条件的transacion
    std::vector<TransactionState> transactions;
    // 刷新过程中记录刷新状态,这里需要注意到,整个刷新过程共用同一个flushState
    // 因此,针对多个Transaction中操作同一个Buffer的情况,都可以通过flushState汇总记录
    TransactionFlushState flushState;
    flushState.queueProcessTime = systemTime();

    int lastTransactionsPendingBarrier = 0;
    int transactionsPendingBarrier = 0;
 // 这里进行循环的原因是依赖Barrier的Transaction可能与满足Barrier条件的Transaction
    // 处于不同的applyToken中,通过循环执行,直到Transaction Barrier计数不在发生变化,
    // 可以尽可能地解决Barrier的依赖链,确保所有依赖于Barrier的Transaction可以被被正确处理
    do {
        lastTransactionsPendingBarrier = transactionsPendingBarrier;
        transactionsPendingBarrier = flushPendingTransactionQueues(transactions, flushState);
    } while (lastTransactionsPendingBarrier != transactionsPendingBarrier);

    // 处理针对Unsignaled Buffer Latch机制符合AutoSingleLayer模式的Transaction
    applyUnsignaledBufferTransaction(transactions, flushState);
    // pending Transaction计数 -1
    mPendingTransactionCount.fetch_sub(transactions.size());
    
    ATRACE_INT("TransactionQueue", static_cast<int>(mPendingTransactionCount.load()));
    return transactions;
}

这里会对所有处于mLocklessTransactionQueue列表中的Transaction进行分类,相同Token的放入mPendingTransactionQueues的同一个队列中。

mPendingTransactionQueues是一个<Tranaction Token、TransactionState>形式的映射表:

arduino 复制代码
// frameworks/native/services/surfaceflinger/FrontEnd/TransactionHandler.h

std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash>
        mPendingTransactionQueues;

接下来遍历mPendingTransactionQueues映射表,并对所有TransactionState队列进行筛选:

cpp 复制代码
// frameworks/native/services/surfaceflinger/FrontEnd/TransactionHandler.cpp

int TransactionHandler::flushPendingTransactionQueues(std::vector<TransactionState>& transactions,
                                                      TransactionFlushState& flushState) {
    // 用于统计带有Buffer barrier的Transaction个数
    int transactionsPendingBarrier = 0;
    auto it = mPendingTransactionQueues.begin();
    // 遍历mPendingTransactionQueues映射表
    while (it != mPendingTransactionQueues.end()) {
        auto& [applyToken, queue] = *it;
        // 以Token为单位,遍历TransactionState队列
        while (!queue.empty()) {
            // 获得TransactionState对象,并将其地址赋值给flushState.transaction
            auto& transaction = queue.front();
            flushState.transaction = &transaction;
            // 筛选TransactionState,确定是否能在该帧进行提交
            auto ready = applyFilters(flushState);
            // 筛选返回结果为NotReadyBarrier时,说明该Transaction中存在Buffer barrier,
            // 不会参与到此帧合成,并且当前token对应的整个队列全部结束遍历
            if (ready == TransactionReadiness::NotReadyBarrier) {
                // 计数+1, 结束该Transaction的Token的所有遍历
                transactionsPendingBarrier++;
                break;
            } else if (ready == TransactionReadiness::NotReady) {
                // 筛选返回结果为NotReady时, 说明该Transaction未准备好,
                // 不会参与到此帧合成,并且当前token对应的整个队列全部结束遍历
                break;
            } else if (ready == TransactionReadiness::NotReadyUnsignaled) {
                // 筛选返回结果为NotReadyUnsignaled,
                flushState.queueWithUnsignaledBuffer = applyToken;
                break;
            }
            // 能执行到这里,说明筛选结果为Ready,此时将TransactionState从映射表中移除,
            // 添加到transactions列表中为提交做准备
            popTransactionFromPending(transactions, flushState, queue);
        }

        // 如果pendingTransaction队列为空,说明已全部移动到transactions中,
        // 此时从mPendingTransactionQueues中移除对应token,否则还需要继续保留
        if (queue.empty()) {
            it = mPendingTransactionQueues.erase(it);
        } else {
            it = std::next(it, 1);
        }
    }
    // 返回存在barrier的Transaction Token个数
    return transactionsPendingBarrier;
}

以上方法中,将通过applyFilters()方法开始对Transaction进行筛选。进行筛选时,筛选器返回4类结果值:

  • Ready:表示Transaction已满足所有条件,会在当前帧进行提交;

  • NotReady:表示该Transaction未满足在当前帧提交的条件,不会在当前帧进行提交,如acquireFence信号未Signaled、present time时间戳未到达....

  • NotReadyBarrier:表示该Transaction中存在Buffer barrier, 不会在当前帧进行提交;

  • NotReadyUnsignaled:这个返回值专为Unsignaled Buffer Latch功能设计,它表示当Unsignaled Buffer Latch功能配置为AutoSingleLayer模式时,针对仅存在一个Transaction待提交时,会忽略acquireFence状态的检查,以此来优化性能。

当返回结果为Ready时,表示可以在该帧进行提交并参与合成,会将TransactionState对象从mPendingTransactionQueues映射表中移除,并添加到transactions列表中。

TransactionHandler::popTransactionFromPending()方法中移除操作如下:

cpp 复制代码
// frameworks/native/services/surfaceflinger/FrontEnd/TransactionHandler.cpp

void TransactionHandler::popTransactionFromPending(std::vector<TransactionState>& transactions,
                                                   TransactionFlushState& flushState,
                                                   std::queue<TransactionState>& queue) {
    // 取出队列中队头元素
    auto& transaction = queue.front();
    flushState.firstTransaction = false;
    // 从mStalledTransactions中移除队头transaction id
    removeFromStalledTransactions(transaction.id);
    // 将队头Transaction添加到Ready Tranaction列表中
    transactions.emplace_back(std::move(transaction));
    // 将队头元素从pending队列中移除
    queue.pop();

    // 返回Ready Transaction列表中最后一个元素
    auto& readyToApplyTransaction = transactions.back();
    // 针对带有Buffer更新的Layer,将LayerHandle和framNumber保存到flushState.bufferLayersReadyToPresent中
    // 用于解除Barrier Buffer对该token的所在Transaction列表的阻塞
    readyToApplyTransaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
        const bool frameNumberChanged =
                state.bufferData->flags.test(BufferData::BufferDataChange::frameNumberChanged);
        // frameNumber有更新时,将实际Buffer的frameNumber保存
        if (frameNumberChanged) {
            flushState.bufferLayersReadyToPresent.emplace_or_replace(state.surface.get(),
                                                                     state.bufferData->frameNumber);
        } else {
            // frameNumber没有更新时,设置一个最大值,确保能够解除barrier限制
            flushState.bufferLayersReadyToPresent
                    .emplace_or_replace(state.surface.get(), std::numeric_limits<uint64_t>::max());
        }
    });
}

下面详细看下两个TransactionFilter的实现。

3.1、Timeline状态筛选

SurfaceFlinger::transactionReadyTimelineCheck()方法用于筛选Transaction所携带指定时间戳是否满足在当前帧进行提交与合成:

cpp 复制代码
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyTimelineCheck(
        const TransactionHandler::TransactionFlushState& flushState) {

    using TransactionReadiness = TransactionHandler::TransactionReadiness;
    const auto& transaction = *flushState.transaction;
    // 获取Transaction携带的desiredPresentTime时间戳
    TimePoint desiredPresentTime = TimePoint::fromNs(transaction.desiredPresentTime);

    // 如果业务进程主动设置了desiredPresentTime,且该时间戳小于mExpectedPresentTime 1s,
    // 则该Transaction在这一帧不会参与合成
    if (!transaction.isAutoTimestamp && desiredPresentTime >= mExpectedPresentTime &&
        desiredPresentTime < mExpectedPresentTime + 1s) {
        return TransactionReadiness::NotReady;
    }

    // 检查VSync事件是否与业务进程目标帧率是否同步
    if (!mScheduler->isVsyncValid(mExpectedPresentTime, transaction.originUid)) {
        return TransactionReadiness::NotReady;
    }

    // 判断当前帧是否过早到达
    if (transaction.isAutoTimestamp && frameIsEarly(expectedPresentTime, vsyncId)) {
        return TransactionReadiness::NotReady;
    }
    return TransactionReadiness::Ready;
}

desiredPresentTime表示Client端指定的期望该帧显示的时间戳。该值由BBQ中的BufferItem::mIsAutoTimestamp属性决定设置方式。

  • BufferItem::mIsAutoTimestamp为true时,表示自动设置时间戳,这种情况下Transaction::mIsAutoTimestamp属性默认为true,会在Transaction::setBuffer()时将当前时间戳作为desiredPresentTime传递给sf;
  • BufferItem::mIsAutoTimestamp为false时,Transaction::mIsAutoTimestamp也将被更新为false,这种情况下BBQ中会在queueBuffer操作时将当前时间戳更新给desiredPresentTime。

BufferItem::mIsAutoTimestamp属性的设置也是从queueBuffer操作开始,如在Surface中:

cpp 复制代码
// frameworks/native/libs/gui/Surface.cpp

int Surface::setBuffersTimestamp(int64_t timestamp)
{
    // 设置类型
    mTimestamp = timestamp;
    return NO_ERROR;
}

mExpectedPresentTime表示sf中该帧预期显示的时间戳,根据VSYNC信号及对应的配置计算获得,通过该时间戳可以避免帧过早或过晚显示。

3.2、BufferReady状态筛选

SurfaceFlinger::transactionReadyBufferCheck()方法用于筛选Transaction所携带的GraphicBuffer是否满足在当前帧进行提交并参与合成:

cpp 复制代码
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferCheck(
        const TransactionHandler::TransactionFlushState& flushState) {
    using TransactionReadiness = TransactionHandler::TransactionReadiness;
    auto ready = TransactionReadiness::Ready;
    // 在TransactionState中处理遍历返回结果
    flushState.transaction->traverseStatesWithBuffersWhileTrue([&](const layer_state_t& s,
                                                                   const std::shared_ptr<
                                                                           renderengine::
                                                                                   ExternalTexture>&
                                                                           externalTexture)
                                                                       -> bool {
        sp<Layer> layer = LayerHandle::getLayer(s.surface);
        const auto& transaction = *flushState.transaction;
        // Transaction Barrier检查
        // 当Transaction中存在携带Barrier的BufferData时,检查是否需要解除此次Barrier
        if (s.bufferData->hasBarrier) {
            // 当对应layer的producerId已经大于之前设置时,这种情况认为旧Barrier已经过时,直接释放
            // 同时从TransactionState.states列表中删除
            if (layer->getDrawingState().barrierProducerId > s.bufferData->producerId) {
                layer->callReleaseBufferCallback(s.bufferData->releaseBufferListener,
                                                 externalTexture->getBuffer(),
                                                 s.bufferData->frameNumber,
                                                 s.bufferData->acquireFence);
                return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL;
            }
            // 当对应Layer的barrierFrameNumber小于此Transaction中bufferData所携带
            // barrierFrameNumber时,说明对应Layer还没有更新比该Barrier更新一帧的Buffer
            // 接下来需要判断是否移除barrier,如果这一帧其他Transaction中携带了更新一帧的Buffer,
            // 则当前Barrier完成任务,会被移除掉 
            if (layer->getDrawingState().barrierFrameNumber < s.bufferData->barrierFrameNumber) {
                // 如果flushState.bufferLayersReadyToPresent列表中已经记录了对应Layer、
                // 且列表中Layer的frameNumber大于当前Transaction中该Layer携带的bufferData
                // 的frameNumber,这种情况说明已经在其他Transaction中更新了对应Layer的
                // BufferData,此时解除Barrier,可以参与到该帧的合成过程中。
                // 否则Barrier依旧有效,返回NotReadyBarrier
                const bool willApplyBarrierFrame =
                        flushState.bufferLayersReadyToPresent.contains(s.surface.get()) &&
                        ((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >=
                          s.bufferData->barrierFrameNumber));
                if (!willApplyBarrierFrame) {
                    ready = TransactionReadiness::NotReadyBarrier;
                    return TraverseBuffersReturnValues::STOP_TRAVERSAL;
                }
            }
        }
        

        // Backpressure机制检查,BBQ中默认开启backpressure背压机制,处理Buffer队列积压场景
        // 在这一帧时当其他Transaction对同一Layer提交了Buffer时,当前Transaction则不会提交,
        // 直到下次刷新时进行提交
        const bool hasPendingBuffer =
                flushState.bufferLayersReadyToPresent.contains(s.surface.get());
        if (layer->backpressureEnabled() && hasPendingBuffer && transaction.isAutoTimestamp) {
            ready = TransactionReadiness::NotReady;
            return TraverseBuffersReturnValues::STOP_TRAVERSAL;
        }

        // Fence状态及AutoSingleLayer模式检查
        // 获取Unsignaled Buffer Latch机制配置是否为LatchUnsignaledConfig::Always
        // LatchUnsignaledConfig::Always则直接跳过Fence状态检查
        const bool checkAcquireFence = enableLatchUnsignaledConfig != LatchUnsignaledConfig::Always;
        const bool acquireFenceAvailable = s.bufferData &&
                s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) &&
                s.bufferData->acquireFence;
        // 获取acquireFence状态是否已经为Signaled状态
        const bool fenceSignaled = !checkAcquireFence || !acquireFenceAvailable ||
                s.bufferData->acquireFence->getStatus() != Fence::Status::Unsignaled;

        if (!fenceSignaled) {
            // 检查Unsignaled Buffer Latch机制是否满足AutoSingleLayer模式
            const bool allowLatchUnsignaled =
                    shouldLatchUnsignaled(layer, s, transaction.states.size(),
                                          flushState.firstTransaction);
            // 如果Unsignaled Buffer Latch满足AutoSingleLayer模式,返回NotReadyUnsignaled
            if (allowLatchUnsignaled) {
                ready = TransactionReadiness::NotReadyUnsignaled;
            } else {
                // 否则返回NotReady
                ready = TransactionReadiness::NotReady;
                auto& listener = s.bufferData->releaseBufferListener;
                // 如果Transaction大于4s还没有提交,触发onTransactionQueueStalled回调
                if (listener &&
                    (flushState.queueProcessTime - transaction.postTime) >
                            std::chrono::nanoseconds(4s).count()) {
                    mTransactionHandler
                            .onTransactionQueueStalled(transaction.id, listener,
                                                       "Buffer processing hung up due to stuck "
                                                       "fence. Indicates GPU hang");
                }
                return TraverseBuffersReturnValues::STOP_TRAVERSAL;
            }
        }


        return TraverseBuffersReturnValues::CONTINUE_TRAVERSAL;
    });
    return ready;
}

以上方法中,通过三个状态检查Buffer是否满足提交条件:

  • Transaction Barrier机制检查:Buffer barrier实际上也是一个帧序列号,如果一个Transaction携带了一个Buffer barrier时,会阻塞比帧序列号比它小的Transaction提交,这是BLAST Sync机制中的一部分,主要用于控制不同进程间的内容在同一帧进行提交合成,如分屏场景下拖动滑杆时两个应用的同步显示。
  • acquireFence状态检查:acquireFence是指由业务进程跟随Buffer传递给surfaceflinger进程、并进一步传递给HWC的Fence对象,用于surfaceflinger或HWC中检查GPU是否完成该Buffer的处理。只有当acquireFence状态为有信号状态时,才能对对应Buffer所在的Transaction进行提交;
  • Unsignaled Buffer Latch机制检查:Unsignaled Buffer Latch机制是对acquireFence状态检查的额外扩展,如果Unsignaled Buffer Latch配置为AutoSingleLayer模式,那么对于只携带一个了Layer相关属性的Transaction,会跳过acquireFence状态检查,即便acquireFence没有变为有信号状态时,也可以进行提交后参与到合成过程,以此来优化性能。

此外,在执行traverseStatesWithBuffersWhileTrue()方法时,会根据返回值对TransactioState做额外的处理,比如当返回值为DELETE_AND_CONTINUE_TRAVERSAL时,会从transaction列表中删除,也将不会参与这一帧合成过程:

cpp 复制代码
// frameworks/native/services/surface flinger/TransactionState.h

void traverseStatesWithBuffersWhileTrue(Visitor&& visitor) {
    for (auto state = states.begin(); state != states.end();) {
        if (state->state.hasBufferChanges() && state->externalTexture && state->state.surface) {
            int result = visitor(state->state, state->externalTexture);
            // 返回STOP_TRAVERSAL时,终止此次遍历
            if (result == STOP_TRAVERSAL) return;
            // 返回DELETE_AND_CONTINUE_TRAVERSAL时,将过期Transaction从队列中删除
            if (result == DELETE_AND_CONTINUE_TRAVERSAL) {
                state = states.erase(state);
                continue;
            }
        }
        state++;
    }
}

四、Transaction Barrier机制

Transaction Barrier机制主要是用于实现不同进程在同一帧的同步显示。Android 12引入了BLAST Sync架构后,可以将不同进程的显示内容在同一帧进行输出,从而实现跨进程的动画同步。其基础就是利用Transaction的跨进程传递特性,将不同进程间的Transaction通过BLAST Sync架构中的组件进行合并,然后传递给surfaceflinger进程参与合成。

在这个过程中,由于Transaction进行了跨进程传递以及合并,对应的applyToken也将发生变化,而每个业务进程在绘制过程中还有单独的Transaction会更新Buffer,当两边同时想sf进程进行apply时,就存在帧乱序的情况。

因此,在这种情况下,通过设置一个Transaction barrier,来防止出现帧乱序情况。

4.1、Transaction Barrier的设置

通过BLASTBufferQueue::syncNextTransaction()方法设置TransactionBarrier,如在ViewRootImpl中:

cpp 复制代码
// frameworks/base/core/java/android/view/ViewRootImpl.java

// 设置barrier
boolean result = mBlastBufferQueue.syncNextTransaction(transaction -> {
    Runnable timeoutRunnable = () -> Log.e(mTag,
            "Failed to submit the sync transaction after 4s. Likely to ANR "
                    + "soon");
    mHandler.postDelayed(timeoutRunnable, 4000L * Build.HW_TIMEOUT_MULTIPLIER);
    transaction.addTransactionCommittedListener(mSimpleExecutor,
            () -> mHandler.removeCallbacks(timeoutRunnable));
    surfaceSyncGroup.addTransaction(transaction);
    surfaceSyncGroup.markSyncReady();
});

以上方法调用进入native层后,会创建一个新的Transaction对象:

cpp 复制代码
// frameworks/native/libs/gui/BLASTBufferQueue.cpp

bool BLASTBufferQueue::syncNextTransaction(
        std::function<void(SurfaceComposerClient::Transaction*)> callback,
        bool acquireSingleBuffer) {
    ......
    // 回调函数
    mTransactionReadyCallback = callback;
    // 创建新的Transaction对象
    mSyncTransaction = new SurfaceComposerClient::Transaction();
    // 默认为true,表示只生效一帧
    mAcquireSingleBuffer = acquireSingleBuffer;
    return true;
}

当有Buffer更新时,将Buffer、Buffer barrier更新给这个新Transaction对象后,并通过传入的回调方法将新Transaction对象返回给调用处:

cpp 复制代码
// frameworks/native/libs/gui/BLASTBufferQueue.cpp

status_t BLASTBufferQueue::acquireNextBufferLocked(
        const std::optional<SurfaceComposerClient::Transaction*> transaction) {

    ......

    // 是否使用syncTransaction
    SurfaceComposerClient::Transaction localTransaction;
    bool applyTransaction = true;
    SurfaceComposerClient::Transaction* t = &localTransaction;
    if (transaction) {
        t = *transaction;
        applyTransaction = false;
    }

    BufferItem bufferItem;

    status_t status =
            mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
    

    auto buffer = bufferItem.mGraphicBuffer;
    ......
    // 更新Buffer
    t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, mProducerId,
                 releaseBufferCallback);
    ......
    // 如果applyTransaction为true,说明不存在syncTransaction,直接进行apply
    if (applyTransaction) {
        t->setApplyToken(mApplyToken).apply(false, true);
        mAppliedLastTransaction = true;
        mLastAppliedFrameNumber = bufferItem.mFrameNumber;
   } else {
        // 否则说明存在syncTransaction,会设置一个barrier,不会进行apply,
        // 并且这个t将跟随回调方法返回
        t->setBufferHasBarrier(mSurfaceControl, mLastAppliedFrameNumber);
        mAppliedLastTransaction = false;
    }
    return OK;
}

可以看到,Barrier实际上是当前Buffer的帧序号,通过Transaction::setBufferHasBarrier()方法设置给Transaction:

cpp 复制代码
// frameworks/native/libs/gui/SurfaceComposerClient.cpp

SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBufferHasBarrier(
        const sp<SurfaceControl>& sc, uint64_t barrierFrameNumber) {
    layer_state_t* s = getLayerState(sc);
    if (!s) {
        mStatus = BAD_INDEX;
        return *this;
    }
    // 将s->bufferData->hasBarrier属性设置为true
    s->bufferData->hasBarrier = true;
    // 设置buffer barrier帧序列号
    s->bufferData->barrierFrameNumber = barrierFrameNumber;
    return *this;
}

进入sf进程后,将根据s->bufferData->hasBarrier和s->bufferData->barrierFrameNumber来决定是否阻塞Transaction的提交。

4.2、Transaction Barrier的解除

在业务进程中,Transaction Barrier的解除根据设置时acquireSingleBuffer参数的不同,分为两种形式:

  1. 如果设置时没有指定acquireSingleBuffer,则该属性默认为true,表示Barrier仅对一帧Buffer生效,完成设置后自动解除。

解除实现在BLASTBufferQueue::onFrameAvailable()方法中:

cpp 复制代码
// frameworks/native/libs/gui/BLASTBufferQueue.cpp

void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
    std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
    SurfaceComposerClient::Transaction* prevTransaction = nullptr;

    {
        ......
        if (syncTransactionSet) {
            // 将此次Buffer帧序列号添加到mSyncedFrameNumbers列表中,用于跟踪该sync transaction是否
            // 已提交给sf,在收到transactionCommited()回调或release后会从mSyncedFrameNumbers
            // 中移除
            mSyncedFrameNumbers.emplace(item.mFrameNumber);
            // 有sync transaction时,获取不到buffer时会进入等待状态,确保此次sync操作完成
            while (acquireNextBufferLocked(mSyncTransaction) == BufferQueue::NO_BUFFER_AVAILABLE) {
                mCallbackCV.wait(_lock);
            }

            // 注册TransactionCommitted回调,在sf中完成commit操作后会触发该回调
            incStrong((void*)transactionCommittedCallbackThunk);
            mSyncTransaction->addTransactionCommittedCallback(transactionCommittedCallbackThunk,
                                                              static_cast<void*>(this));
            // mAcquireSingleBuffer为true时,syncTransaction只生效一帧,后立即解除
            if (mAcquireSingleBuffer) {
                prevCallback = mTransactionReadyCallback;
                prevTransaction = mSyncTransaction;
                mTransactionReadyCallback = nullptr;
                mSyncTransaction = nullptr;
            }
        } else if (!waitForTransactionCallback) {
            // 说明是正常操作,执行正常acquireBuffer操作
            acquireNextBufferLocked(std::nullopt);
        }
        // 如果waitForTransactionCallback为true,说明上一帧sync transaction还未完成,那么这一帧
        // 既不会获取到buffer、也不会阻塞当前线程
    }
    // 执行sync transaction设置的回调
    if (prevCallback) {
        prevCallback(prevTransaction);
    }
}
  1. 如果设置时指定acquireSingleBuffer为false,则必须通过显式调用进行解除。目前这种使用场景不多。

显式解除通过BLASTBufferQueue::stopContinuousSyncTransaction()方法:

cpp 复制代码
// frameworks/native/libs/gui/BLASTBufferQueue.cpp

void BLASTBufferQueue::stopContinuousSyncTransaction() {
    std::function<void(SurfaceComposerClient::Transaction*)> prevCallback = nullptr;
    SurfaceComposerClient::Transaction* prevTransaction = nullptr;
    {
        std::lock_guard _lock{mMutex};
        // 上一次callback
        prevCallback = mTransactionReadyCallback;
        // 上一次prevTransaction
        prevTransaction = mSyncTransaction;
        // 重置mTransactionReadyCallback对象
        mTransactionReadyCallback = nullptr;
        // 重置mSyncTransaction对象
        mSyncTransaction = nullptr;
        mAcquireSingleBuffer = true;
    }
    // 触发一次callback回调
    if (prevCallback) {
        prevCallback(prevTransaction);
    }
}

在sf进程中,则根据Buffer的frameNumber决定是否移除barrier的限制。

当某个Transaction完成筛选,从待提交队列中移除时,会将Buffer的frameNumber及对应Layer记录在flushState.bufferLayersReadyToPresent中:

cpp 复制代码
// frameworks/native/services/surfaceflinger/FrontEnd/TransactionHandler.cpp

void TransactionHandler::popTransactionFromPending(std::vector<TransactionState>& transactions,
                                                   TransactionFlushState& flushState,
                                                   std::queue<TransactionState>& queue) {
    // 取出队列中队头元素
    auto& transaction = queue.front();
    flushState.firstTransaction = false;
    // 从mStalledTransactions中移除队头transaction id
    removeFromStalledTransactions(transaction.id);
    // 将队头Transaction添加到Ready Tranaction列表中
    transactions.emplace_back(std::move(transaction));
    // 将队头元素从pending队列中移除
    queue.pop();

    // 返回Ready Transaction列表中最后一个元素
    auto& readyToApplyTransaction = transactions.back();
    // 针对带有Buffer更新的Layer,将LayerHandle和framNumber保存到flushState.bufferLayersReadyToPresent中
    // 用于解除Barrier Buffer对该token的所在Transaction列表的阻塞
    readyToApplyTransaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
        const bool frameNumberChanged =
                state.bufferData->flags.test(BufferData::BufferDataChange::frameNumberChanged);
        // frameNumber有更新时,将实际Buffer的frameNumber保存
        if (frameNumberChanged) {
            flushState.bufferLayersReadyToPresent.emplace_or_replace(state.surface.get(),
                                                                     state.bufferData->frameNumber);
        } else {
            // frameNumber没有更新时,设置一个最大值,确保能够解除barrier限制
            flushState.bufferLayersReadyToPresent
                    .emplace_or_replace(state.surface.get(), std::numeric_limits<uint64_t>::max());
        }
    });
}

然后在检查Barrier状态时,当flushState.bufferLayersReadyToPresent中的framenumber值大于被检查TransactionState携带的s.bufferData->barrierFrameNumber值时,将解除阻塞。

五、Unsignaled Buffer Latch机制

Unsignaled Buffer Latch机制是对acquireFence状态检查的额外扩展,可通过配置来设置不同的模式:

cpp 复制代码
// frameworks/native/services/surfaceflinger/SurfaceFlinger.h

enum class LatchUnsignaledConfig {
    // 表示Unsignaled Buffer Latch机制关闭,当acquireFence处于无信号状态时,
    // 不会进行对应Tranaction的提交
    Disabled,
    // 表示为AutoSingleLayer模式,对于只携带一个了Layer属性的Transaction,
    // 会跳过acquireFence状态检查
    AutoSingleLayer,
    // 表示Unsignaled Buffer Latch机制开启,所有Transaction都会跳过acquireFence状态检查
    Always,
};

配置时通过debug.sf.auto_latch_unsignaleddebug.sf.latch_unsignaled属性指定模式,在sf启动时会读取该属性:

cpp 复制代码
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() {
    if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, true)) {
        return LatchUnsignaledConfig::AutoSingleLayer;
    }

    return LatchUnsignaledConfig::Disabled;
}

在检查acquireFence状态时,对于未Signaled的acquireFence,会通过SurfaceFlinger::shouldLatchUnsignaled()方法检查是否满足AutoSingleLayer模式:

cpp 复制代码
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

bool SurfaceFlinger::shouldLatchUnsignaled(const layer_state_t& state, size_t numStates,
                                           bool firstTransaction) const {
    // Unsignaled Buffer Latch机制关闭时,返回false
    if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Disabled) {
        return false;
    }

    // 只针对带有一个Layer属性的Transaction
    if (numStates != 1) {
        return false;
    }

    if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer) {
        // 队列中队头元素
        if (!firstTransaction) {
            return false;
        }

        if (mScheduler->vsyncModulator().isVsyncConfigEarly()) {
            return false;
        }
    }

    return true;
}

如果满足AutoSingleLayer模式,筛选结果返回NotReadyUnsignaled,并在完成所有Transaction的筛选后,再通过TransactionHandler::applyUnsignaledBufferTransaction()方法将Transaction从待提交队列中移除:

cpp 复制代码
// frameworks/native/services/surfaceflinger/FrontEnd/TransactionHandler.cpp

void TransactionHandler::applyUnsignaledBufferTransaction(
        std::vector<TransactionState>& transactions, TransactionFlushState& flushState) {
    if (!flushState.queueWithUnsignaledBuffer) {
        return;
    }

    // 当仅存在一个AutoSingleLayer的Transaction时才会提交
    if (!transactions.empty()) {
        return;
    }
    // 从队列中移除
    auto it = mPendingTransactionQueues.find(flushState.queueWithUnsignaledBuffer);
    LOG_ALWAYS_FATAL_IF(it == mPendingTransactionQueues.end(),
                        "Could not find queue with unsignaled buffer!");

    auto& queue = it->second;
    popTransactionFromPending(transactions, flushState, queue);
    if (queue.empty()) {
        it = mPendingTransactionQueues.erase(it);
    }
}

关于更多Unsignaled Buffer Latch机制的资料,参考官方文档:

source.android.com/docs/core/g...

相关推荐
jiet_h3 小时前
Android Compose: `remember` 与 `ViewModel` 保存数据的优缺点对比
android
haoqi好奇3 小时前
uniapp+node+mysql接入deepseek实现流式输出
android·mysql·uni-app
alexhilton4 小时前
高效地在Jetpack Compose中设计UI组件
android·kotlin·android jetpack
恋猫de小郭4 小时前
Flutter 小技巧之通过 MediaQuery 优化 App 性能
android·前端·flutter
CYRUS_STUDIO4 小时前
安卓逆向魔改版 Base64 算法还原
android·算法·逆向
CYRUS_STUDIO5 小时前
安卓实现魔改版 Base64 算法
android·算法·逆向
盖盖衍上6 小时前
2-002:MySQL 索引的最左前缀匹配原则是什么?
android·数据库·mysql
然后就去远行吧7 小时前
小程序 wxml 语法 —— 37 setData() - 修改对象类型数据
android·前端·小程序
熙曦Sakura8 小时前
【MySQL】数据类型
android·mysql·adb