addTransactionCommittedListener:
/**
* Request to add a {@link TransactionCommittedListener}.
*
* The callback is invoked when transaction is applied and the updates are ready to be
* presented. This callback does not mean buffers have been released! It simply means that
* any new transactions applied will not overwrite the transaction for which we are
* receiving a callback and instead will be included in the next frame. If you are trying
* to avoid dropping frames (overwriting transactions), and unable to use timestamps (Which
* provide a more efficient solution), then this method provides a method to pace your
* transaction application.
*
* @param executor The executor that the callback should be invoked on.
* @param listener The callback that will be invoked when the transaction has been
* committed.
*/
@NonNull
public Transaction addTransactionCommittedListener(
@NonNull @CallbackExecutor Executor executor,
@NonNull TransactionCommittedListener listener) {
TransactionCommittedListener listenerInner =
() -> executor.execute(listener::onTransactionCommitted);//(1)
nativeAddTransactionCommittedListener(mNativeObject, listenerInner); //(2)
return this;
}
上一节讲到这个addTransactionCommittedListener方法,具体功能是为了在transaction提交到SurfaceFlinger侧时,回调这个listenerInner的onTransactionCommitted函数。本次就来记录下这个流程的分析。这里也解释下mNativeObject其实就是一个Java类中定义的long型变量,他指向一个本地对象的地址或标志符,存储在Java对象的成员变量中。因为一直也没找到这个函数相关的介绍,所以我也只能硬着头皮一点一点的跟到native层的代码,这也导致了本文多次修改,不过目前也算是梳理清楚了,总之不能误导读者。
1、addTransactionCommittedListener方法的功能:
如上述代码可见(1)处,就是创建了一个新的TransactionCommittedListener类的对象listenerInner。这里还是采用了lambda表达式,完整的写法应该是:
TransactionCommittedListener listenerInner = new TransactionCommittedListener() {
@Override
public void onTransactionCommitted() {
executor.execute(listener::onTransactionCommitted);
}
};
这里可见listenerInner就是一个新建的TransactionCommittedListener类对象,重写了其onTransactionCommitted方法。而重写的方法体就是通过excutor创建一个线程,去执行一个Runnable对象,而这个Runnable对象就是listener::onTransactionCommitted方法,这里又涉及到了一个新的TransactionCommittedListener对象listener,这个listener,就是在BLASTSyncEngine里的这一块定义的:
merged.addTransactionCommittedListener(® -> { r.run(); }, callback::onCommitted);
从上面的代码可见,这个listener对象的onTransactionCommitted方法就是callback对象的onCommitted方法,这个地方详情可见上一个博客的解释。
所以到这里就知道了(1)处的功能就是创建一个TransactionCommittedListener类的对象,listenerInner,并将其onTransactionCommitted()的方法重写为callback对象的onCommitted方法。
那下面就到了(2)处的详解了,这里涉及到了JNI的调用。nativeAddTransactionCommittedListener方法的实现需要去查找其定义处,看到android_view_SurfaceControl.cpp处,如下代码(3)处,表示nativeAddTransactionCommittedListener在本文件中对应的方法就是(void*)
nativeAddTransactionCommittedListener。
{"nativeAddTransactionCommittedListener", "(JLandroid/view/SurfaceControl$TransactionCommittedListener;)V",
(void*) nativeAddTransactionCommittedListener }, //(3)
2、nativeAddTransactionCommittedListener:
在cpp文件中找到这个函数的定义:
static void nativeAddTransactionCommittedListener(JNIEnv* env, jclass clazz, jlong transactionObj,
jobject transactionCommittedListenerObject) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); //(4)
void* context =
new TransactionCommittedListenerWrapper(env, transactionCommittedListenerObject); //(5)
transaction->addTransactionCommittedCallback(TransactionCommittedListenerWrapper::
transactionCallbackThunk,
context); //(6)
}
代码(4)处其实就是通过reinterpret_cast进行类型转换,将transactionObj(前面的mNativeObject参数)转换成一个SurfaceComposerClient::Transaction类型的指针,然后赋值给transaction。到代码(5)处就是创建一个TransactionCommittedListenerWrapper类型的对象,并赋值给void类型的指针context,而void就是一个通用类型的指针,也就是说他可以指向任何类型。 而我们在SurfaceControl.java中通过JNI调用到这里时,将listenerInner传入的就是transactionCommittedListenerObject之中,那么现在,我们又通过这个transactionCommittedListenerObject构建了一个TransactionCommittedListenerWrapper类型的对象,所以listenerInner就被封装到了这个context指针指向的对象之中。
class TransactionCommittedListenerWrapper {
public:
explicit TransactionCommittedListenerWrapper(JNIEnv* env, jobject object) {
env->GetJavaVM(&mVm); //(7)
mTransactionCommittedListenerObject = env->NewGlobalRef(object); //(8)
LOG_ALWAYS_FATAL_IF(!mTransactionCommittedListenerObject, "Failed to make global ref");
}
void callback() {
JNIEnv* env = getenv();
env->CallVoidMethod(mTransactionCommittedListenerObject,
gTransactionCommittedListenerClassInfo.onTransactionCommitted);
}
………………………………………………
private:
jobject mTransactionCommittedListenerObject;
JavaVM* mVm;
}
根据上面的构造函数,找到TransactionCommittedListenerWrapper的构造方法,如上可见,代码(7)处就是通过env获取当前线程的JavaVM实例,然后将其存储在mVm指针中,这样可以再JNI环境中保存对java虚拟机的引用,并在需要时使用他进行进一步的JNI调用或者操作。
代码(8)处的操作就是将我们在SurfaceControl中传过来listenerInner对象的全局引用,赋值给类TransactionCommittedListenerWrapper的私有变量TransactionCommittedListenerObject ,同时TransactionCommittedListenerWrapper类还提供了一个callback方法,这里暂时先不讲了。
3、addTransactionCommittedCallback:
此方法是类SurfaceComposerClient的一个内部类Transaction的构造方法,查看其定义在SurfaceComposerClient.cpp中,这些类的声明在对应的.h文件中,就不去一个一个说了。
SurfaceComposerClient::Transaction::Transaction() {
mId = generateId(); //(9)
}
SurfaceComposerClient::Transaction::Transaction(const Transaction& other) //(10)
: mId(other.mId),
mForceSynchronous(other.mForceSynchronous),
mTransactionNestCount(other.mTransactionNestCount),
mAnimation(other.mAnimation),
mEarlyWakeupStart(other.mEarlyWakeupStart),
mEarlyWakeupEnd(other.mEarlyWakeupEnd),
mContainsBuffer(other.mContainsBuffer),
mDesiredPresentTime(other.mDesiredPresentTime),
mIsAutoTimestamp(other.mIsAutoTimestamp),
mFrameTimelineInfo(other.mFrameTimelineInfo),
mApplyToken(other.mApplyToken) {
mDisplayStates = other.mDisplayStates;
mComposerStates = other.mComposerStates;
mInputWindowCommands = other.mInputWindowCommands;
mListenerCallbacks = other.mListenerCallbacks;
}
int64_t generateId() {
return (((int64_t)getpid()) << 32) | ++idCounter; //(11)
}
可以看到在构造函数中只有一行代码(9),这里其实就是给Transaction赋了一个id,如(11)处所示,其实和我们的上层代码中的SyncGroup的构造有点相似,不过他加入了线程的pid,放在了64位int数据的高32位,低32位则是一个自增的idCounter。 而(10)处就是根据一个已有的Transaction类型的常量引用参数other构建一个新的Transaction类型的对象。
不过(4)处创建的Transaction类型的对象,其实是通过一个已有的内存中地址,将其转换为一个Transaction类型的指针,所以并不需要调用构造函数。
接着继续去看addTransactionCommittedCallback方法的实现:
SurfaceComposerClient::Transaction&
SurfaceComposerClient::Transaction::addTransactionCommittedCallback(
TransactionCompletedCallbackTakesContext callback, void* callbackContext) {
return addTransactionCallback(callback, callbackContext, CallbackId::Type::ON_COMMIT);
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::addTransactionCallback(
TransactionCompletedCallbackTakesContext callback, void* callbackContext,
CallbackId::Type callbackType) {
auto listener = TransactionCompletedListener::getInstance();//(12)
auto callbackWithContext = std::bind(callback, callbackContext, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3); //(13)
const auto& surfaceControls =
mListenerCallbacks[TransactionCompletedListener::getIInstance()].surfaceControls; //(14)
CallbackId callbackId =
listener->addCallbackFunction(callbackWithContext, surfaceControls, callbackType); //(15)
mListenerCallbacks[TransactionCompletedListener::getIInstance()].callbackIds.emplace(
callbackId); //(16)
return *this;
}
sp<TransactionCompletedListener> TransactionCompletedListener::getInstance() {
std::lock_guard<std::mutex> lock(sListenerInstanceMutex);
if (sInstance == nullptr) {
sInstance = new TransactionCompletedListener;
}
return sInstance;
}
sp<ITransactionCompletedListener> TransactionCompletedListener::getIInstance() {
return static_cast<sp<ITransactionCompletedListener>>(getInstance());//(17)
}
于是终于在这里找到该方法的实现细节了。首先(12)处就是去获取TransactionCompletedListener类的单例并传给listener,然后(13)处就是通过bind函数将callbackContext绑定为callback的第一个参数,还有剩下三个参数暂时先用占位符填充,等到调用时再进行赋值。而这样就创建了一个新的函数对象callbackWithContext。
代码(14)处就是去mListenerCallbacks中拿到一个surfaceControls对象,这里就得讲一下mListenerCallbacks的结构了,在对应的h文件中的声明如下:
std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash>
mListenerCallbacks;
struct CallbackInfo {
std::unordered_set<CallbackId, CallbackIdHash> callbackIds;
std::unordered_set<sp<SurfaceControl>, SCHash> surfaceControls;
};
mListenerCallbacks就是一个unordered_map,他其实就是将数据以键值对的形式保存起来,key就是sp类型,value则是CallbackInfo格式。第三个参数TCLHash就是一个自定义的hash函数,用来计算key的hash值,这里不做讲解。
所以代码(14)处就是根据这个TransactionCompletedListener::getIInstance()的返回值即(17)处的值作为key,在mListenerCallbacks中搜索对应的value值的surfaceControls参数并赋值给surfaceControls。
代码(15)处,就是将(13)处创建的函数对象callbackWithContext,(14)处取出的surfaceControls,以及函数入参callbackType作为参数,去执行listener的addCallbackFunction方法,所以下面再看到addCallbackFunction方法的实现:
CallbackId TransactionCompletedListener::addCallbackFunction(
const TransactionCompletedCallback& callbackFunction,
const std::unordered_set<sp<SurfaceControl>, SurfaceComposerClient::SCHash>&
surfaceControls,
CallbackId::Type callbackType) {
std::lock_guard<std::mutex> lock(mMutex);
startListeningLocked();(18)
CallbackId callbackId(getNextIdLocked(), callbackType); //(19)
mCallbacks[callbackId].callbackFunction = callbackFunction;//(20)
auto& callbackSurfaceControls = mCallbacks[callbackId].surfaceControls; //(21)
for (const auto& surfaceControl : surfaceControls) {
callbackSurfaceControls[surfaceControl->getHandle()] = surfaceControl; //(22)
}
return callbackId;
}
std::unordered_map<CallbackId, CallbackTranslation, CallbackIdHash> mCallbacks
GUARDED_BY(mMutex); //(23)
struct CallbackTranslation { //(24)
TransactionCompletedCallback callbackFunction;
std::unordered_map<sp<IBinder>, sp<SurfaceControl>, SurfaceComposerClient::IBinderHash>
surfaceControls;
};
int64_t TransactionCompletedListener::getNextIdLocked() {
return mCallbackIdCounter++; //(25)
}
struct CallbackTranslation {
TransactionCompletedCallback callbackFunction;
std::unordered_map<sp<IBinder>, sp<SurfaceControl>, SurfaceComposerClient::IBinderHash>
surfaceControls;
};
public:
int64_t id;
enum class Type : int32_t { ON_COMPLETE, ON_COMMIT } type;
CallbackId() {}
CallbackId(int64_t id, Type type) : id(id), type(type) {}
status_t writeToParcel(Parcel* output) const override;
status_t readFromParcel(const Parcel* input) override;
bool operator==(const CallbackId& rhs) const { return id == rhs.id && type == rhs.type; }
};
代码的核心之处就是(22)处,不过得先一步一步的讲过来,因为这里的容器太多了,有点复杂了。首先是在(18)处开始监听,然后用getNextIdLocked()(25处实现)和callbackType构建一个CallbackId的对象callbackId,之后再将callbackFunction放入mCallbacks[callbackId].callbackFunction中。 而 mCallbacks则是如(23)处定义,也是一个unordered_map类型的对象。 所以最后将入参中的surfaceControls一一放入callbackSurfaceControls[surfaceControl->getHandle()]之中。最后返回callbackId。
最后回到代码(16)处,将(15)处返回的callbackId放入到mListenerCallbacks中key为TransactionCompletedListener::getIInstance()的CallbackInfo对象的unordered_set类型的成员变量,callbackIds之中。
所以经过这么一系列的操作,我已经忘记了我最开始的时候在干嘛了。哈哈哈哈,不过没关系,这里再简单梳理一下。
4、流程梳理:
首先是梳理在addTransactionCommittedListener方法中的listenerInner的传递流程,从下图中可见这个listenerInner的封装路径,那么之前说的,在transaction被提交时就会执行这个listenerInner的onTransactionCommitted函数是为什么呢?
这里我是一直跟到了将listenerInner放入了callbackFunction,但是最后在apply到SurfaceFlinger之后,怎么在commit的时候执行回调函数我还是没看懂,这里暂时也只能更新到这里了。
5、补充分析:
在经过一番思索之后,终于想起来这里是什么流程了。
5.1、apply():
status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay) {
………………………………………………………………………………
// For every listener with registered callbacks
for (const auto& [listener, callbackInfo] : mListenerCallbacks) { //(26)
auto& [callbackIds, surfaceControls] = callbackInfo;
if (callbackIds.empty()) {
continue;
}
if (surfaceControls.empty()) {
listenerCallbacks.emplace_back(IInterface::asBinder(listener), std::move(callbackIds));
} else {
// If the listener has any SurfaceControls set on this Transaction update the surface
// state
for (const auto& surfaceControl : surfaceControls) {
layer_state_t* s = getLayerState(surfaceControl);
if (!s) {
ALOGE("failed to get layer state");
continue;
}
std::vector<CallbackId> callbacks(callbackIds.begin(), callbackIds.end());
//标记哪个属性被修改
s->what |= layer_state_t::eHasListenerCallbacksChanged;
//将callback放进layer_state_t结构体中
s->listeners.emplace_back(IInterface::asBinder(listener), callbacks);
}
}
}
………………………………………………………………………………
for (auto const& kv : mComposerStates){ //(27)
composerStates.add(kv.second);
}
sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
{} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
hasListenerCallbacks, listenerCallbacks, mId); //(28)
………………………………………………………………………………
}
layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp<SurfaceControl>& sc) {
auto handle = sc->getLayerStateHandle();
if (mComposerStates.count(handle) == 0) { //(29)
// we don't have it, add an initialized layer_state to our list
ComposerState s;
s.state.surface = handle;
s.state.layerId = sc->getLayerId();
mComposerStates[handle] = s;
}
return &(mComposerStates[handle].state); //(30)
}
在Transaction从应用侧发往SurfaceFlinger侧的时候,需要调用apply函数,这块具体的细节后面会说,在(26)处遍历在(16)处放入的 带有前面传进来的 listenerInner信息的mListenerCallbacks,然后再取出其中的surfaceControls,再遍历surfaceControls中的surfaceControl,并通过getLayerState方法获取SurfaceControl对应的一个layer_state_t结构体。并将刚刚放入mListenerCallbacks中的信息,转存进Transaction类的对象中去。 即在(29)处查看mComposerStates中handle对应的ComposeState是否为空,若为空则添加进去一个新的。而这就是将对应的surfaceControl加入mComposerStates中,然后再于(26)处的循环中,将我们传入的修改和callbacks放入mComposerStates中。
后面又在(27)处,将mComposerStates中的数据放入composerStates之中,然后再于(28)处,将composerStates发送到sf端。
5.2、setTransactionState():
status_t SurfaceFlinger::setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
ATRACE_CALL();
…………………………………………………………………………………
TransactionState state{frameTimelineInfo, states,
displays, flags,
applyToken, inputWindowCommands,
desiredPresentTime, isAutoTimestamp,
uncacheBuffer, postTime,
permissions, hasListenerCallbacks,
listenerCallbacks, originPid,
originUid, transactionId}; //(31)
// Check for incoming buffer updates and increment the pending buffer count.
state.traverseStatesWithBuffers([&](const layer_state_t& state) {
mBufferCountTracker.increment(state.surface->localBinder()); //(32)
});
if (mTransactionTracing) {
mTransactionTracing->addQueuedTransaction(state); //(33)
}
queueTransaction(state);//(34)
…………………………………………………………………………………
}
void SurfaceFlinger::queueTransaction(TransactionState& state) {
……………………………………………………………………
mTransactionQueue.emplace_back(state); //(35)
……………………………………………………………………
}
根据上述的代码中(31),将client侧发送过来的composerStates放入了本地的state中,然后将state再放入mTransactionQueue中如(34)-(35)处;
5.3、回调的调用逻辑:
再看到啥时候把这个消息取出来使用呢?
本来以为昨天写的没问题,但是白天越想越觉得有问题,于是在结合simperf,添加trace点,native层加调用栈,结合分析,终于得到最终的这个调用逻辑。这里坑太多了,特别是native层代码的编译,第一次编译一直报错。而且还有一个坑就是V版本代码和U版本T版本的改动还稍微有点大。
这里可以看到再flushTransactionQueues中会将mTransactionQueue中的数据取出来,这里基本就确定了是这里将传入的callback数据进行回调了。
bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) {
………………………………………………………
while (!mTransactionQueue.empty()) {
auto& transaction = mTransactionQueue.front();
………………………………………………………
transactions.emplace_back(std::move(transaction));
………………………………………………………
mTransactionQueue.pop_front();
}
………………………………………………………
return applyTransactions(transactions, vsyncId);
}
bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo,
Vector<ComposerState>& states,
Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime, bool isAutoTimestamp,
const client_cache_t& uncacheBuffer,
const int64_t postTime, uint32_t permissions,
bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
int originPid, int originUid, uint64_t transactionId) {
……………………………………………………………………………
for (const auto& listener : listenerCallbacks) {
mTransactionCallbackInvoker.addEmptyTransaction(listener);//(36)
}
……………………………………………………………………………
}
void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) {
auto& [listener, callbackIds] = listenerCallbacks;
auto& transactionStatsDeque = mCompletedTransactions[listener];
transactionStatsDeque.emplace_back(callbackIds); //(37)
}
这里看到(36)处:(不过我这边源码是根据T版本的代码来的,我发现U版本以后有点大的改动,存在一点差别,但是整体上还是差不多的)。然后这里就是调用了。TransactionCallbackInvoker类中的addEmptyTransaction方法,将前面传进来的listener放进了该类的transactionStatsDeque容器中,如(37)处。再接着向下走到SurfaceFlinger的setClientStateLocked方法时,就会调用TransactionCallbackInvoker类的sendCallbacks方法。其调用栈如下所示,最终调用到我们一开始注册的回调函数。
onCommitted()
Android_view_SurfaceControl.cpp#transactionCallBckThunk
binder
BackgroundExecutor.cpp#sendCallbacks()
BackgroundExecutor.cpp# BackgroundExecutor()
TransactionCallbackInvoker.cpp#sendCallbacks()
SurfaceFlinger.cpp#setClientStateLocked ()
SurfaceFlinger.cpp#applyTransactionState()
SurfaceFlinger.cpp#applyTransactions()
SurfaceFlinger.cpp#flushTransactionQueues()
SurfaceFlinger.cpp#commit()
BackgroundExecutor::BackgroundExecutor() : Singleton<BackgroundExecutor>() {
mThread = std::thread([&]() {
LOG_ALWAYS_FATAL_IF(sem_init(&mSemaphore, 0, 0), "sem_init failed");
while (!mDone) {
LOG_ALWAYS_FATAL_IF(sem_wait(&mSemaphore), "sem_wait failed (%d)", errno);
ftl::SmallVector<Work*, 10> workItems;
Work* work = mWorks.pop();
while (work) {
workItems.push_back(work);
work = mWorks.pop();
}
// Sequence numbers are guaranteed to be in intended order, as we assume a single
// producer and single consumer.
std::stable_sort(workItems.begin(), workItems.end(), [](Work* left, Work* right) {
return left->sequence < right->sequence;
});
for (Work* work : workItems) {
for (auto& task : work->tasks) {
task();
}
delete work;
}
}
});
}
void BackgroundExecutor::sendCallbacks(Callbacks&& tasks) {
Work* work = new Work();
work->sequence = mSequence;
work->tasks = std::move(tasks);
mWorks.push(work);
mSequence++;
LOG_ALWAYS_FATAL_IF(sem_post(&mSemaphore), "sem_post failed");
}
最后加一张图,这样看起来更清晰一点。