前言
本文基于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
参数的不同,分为两种形式:
- 如果设置时没有指定
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);
}
}
- 如果设置时指定
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_unsignaled
和debug.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机制的资料,参考官方文档: