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...

相关推荐
xiangpanf8 小时前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx11 小时前
安卓线程相关
android
消失的旧时光-194311 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon12 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon12 小时前
VSYNC 信号完整流程2
android
dalancon12 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户693717500138413 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android14 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才14 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶15 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle