WCT系列(五):addTransactionCommittedListener

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");
}

最后加一张图,这样看起来更清晰一点。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值