/* * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "ITransactionCompletedListener" //#define LOG_NDEBUG 0 #include #include #include #include namespace android { namespace { // Anonymous enum class Tag : uint32_t { ON_TRANSACTION_COMPLETED = IBinder::FIRST_CALL_TRANSACTION, ON_RELEASE_BUFFER, LAST = ON_RELEASE_BUFFER, }; } // Anonymous namespace status_t FrameEventHistoryStats::writeToParcel(Parcel* output) const { status_t err = output->writeUint64(frameNumber); if (err != NO_ERROR) return err; if (gpuCompositionDoneFence) { err = output->writeBool(true); if (err != NO_ERROR) return err; err = output->write(*gpuCompositionDoneFence); } else { err = output->writeBool(false); } if (err != NO_ERROR) return err; err = output->writeInt64(compositorTiming.deadline); if (err != NO_ERROR) return err; err = output->writeInt64(compositorTiming.interval); if (err != NO_ERROR) return err; err = output->writeInt64(compositorTiming.presentLatency); if (err != NO_ERROR) return err; err = output->writeInt64(refreshStartTime); if (err != NO_ERROR) return err; err = output->writeInt64(dequeueReadyTime); return err; } status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { status_t err = input->readUint64(&frameNumber); if (err != NO_ERROR) return err; bool hasFence = false; err = input->readBool(&hasFence); if (err != NO_ERROR) return err; if (hasFence) { gpuCompositionDoneFence = new Fence(); err = input->read(*gpuCompositionDoneFence); if (err != NO_ERROR) return err; } err = input->readInt64(&(compositorTiming.deadline)); if (err != NO_ERROR) return err; err = input->readInt64(&(compositorTiming.interval)); if (err != NO_ERROR) return err; err = input->readInt64(&(compositorTiming.presentLatency)); if (err != NO_ERROR) return err; err = input->readInt64(&refreshStartTime); if (err != NO_ERROR) return err; err = input->readInt64(&dequeueReadyTime); return err; } JankData::JankData() : frameVsyncId(FrameTimelineInfo::INVALID_VSYNC_ID), jankType(JankType::None) {} status_t JankData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, frameVsyncId); SAFE_PARCEL(output->writeInt32, jankType); return NO_ERROR; } status_t JankData::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readInt64, &frameVsyncId); SAFE_PARCEL(input->readInt32, &jankType); return NO_ERROR; } status_t SurfaceStats::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeStrongBinder, surfaceControl); SAFE_PARCEL(output->writeInt64, acquireTime); if (previousReleaseFence) { SAFE_PARCEL(output->writeBool, true); SAFE_PARCEL(output->write, *previousReleaseFence); } else { SAFE_PARCEL(output->writeBool, false); } SAFE_PARCEL(output->writeUint32, transformHint); SAFE_PARCEL(output->writeUint32, currentMaxAcquiredBufferCount); SAFE_PARCEL(output->writeParcelable, eventStats); SAFE_PARCEL(output->writeInt32, static_cast(jankData.size())); for (const auto& data : jankData) { SAFE_PARCEL(output->writeParcelable, data); } SAFE_PARCEL(output->writeParcelable, previousReleaseCallbackId); return NO_ERROR; } status_t SurfaceStats::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readStrongBinder, &surfaceControl); SAFE_PARCEL(input->readInt64, &acquireTime); bool hasFence = false; SAFE_PARCEL(input->readBool, &hasFence); if (hasFence) { previousReleaseFence = new Fence(); SAFE_PARCEL(input->read, *previousReleaseFence); } SAFE_PARCEL(input->readUint32, &transformHint); SAFE_PARCEL(input->readUint32, ¤tMaxAcquiredBufferCount); SAFE_PARCEL(input->readParcelable, &eventStats); int32_t jankData_size = 0; SAFE_PARCEL_READ_SIZE(input->readInt32, &jankData_size, input->dataSize()); for (int i = 0; i < jankData_size; i++) { JankData data; SAFE_PARCEL(input->readParcelable, &data); jankData.push_back(data); } SAFE_PARCEL(input->readParcelable, &previousReleaseCallbackId); return NO_ERROR; } status_t TransactionStats::writeToParcel(Parcel* output) const { status_t err = output->writeParcelableVector(callbackIds); if (err != NO_ERROR) { return err; } err = output->writeInt64(latchTime); if (err != NO_ERROR) { return err; } if (presentFence) { err = output->writeBool(true); if (err != NO_ERROR) { return err; } err = output->write(*presentFence); } else { err = output->writeBool(false); } if (err != NO_ERROR) { return err; } return output->writeParcelableVector(surfaceStats); } status_t TransactionStats::readFromParcel(const Parcel* input) { status_t err = input->readParcelableVector(&callbackIds); if (err != NO_ERROR) { return err; } err = input->readInt64(&latchTime); if (err != NO_ERROR) { return err; } bool hasFence = false; err = input->readBool(&hasFence); if (err != NO_ERROR) { return err; } if (hasFence) { presentFence = new Fence(); err = input->read(*presentFence); if (err != NO_ERROR) { return err; } } return input->readParcelableVector(&surfaceStats); } status_t ListenerStats::writeToParcel(Parcel* output) const { status_t err = output->writeInt32(static_cast(transactionStats.size())); if (err != NO_ERROR) { return err; } for (const auto& stats : transactionStats) { err = output->writeParcelable(stats); if (err != NO_ERROR) { return err; } } return NO_ERROR; } status_t ListenerStats::readFromParcel(const Parcel* input) { int32_t transactionStats_size = input->readInt32(); for (int i = 0; i < transactionStats_size; i++) { TransactionStats stats; status_t err = input->readParcelable(&stats); if (err != NO_ERROR) { return err; } transactionStats.push_back(stats); } return NO_ERROR; } ListenerStats ListenerStats::createEmpty( const sp& listener, const std::unordered_set& callbackIds) { ListenerStats listenerStats; listenerStats.listener = listener; listenerStats.transactionStats.emplace_back(callbackIds); return listenerStats; } class BpTransactionCompletedListener : public SafeBpInterface { public: explicit BpTransactionCompletedListener(const sp& impl) : SafeBpInterface(impl, "BpTransactionCompletedListener") { } ~BpTransactionCompletedListener() override; void onTransactionCompleted(ListenerStats stats) override { callRemoteAsync(Tag::ON_TRANSACTION_COMPLETED, stats); } void onReleaseBuffer(ReleaseCallbackId callbackId, sp releaseFence, uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) override { callRemoteAsync(Tag::ON_RELEASE_BUFFER, callbackId, releaseFence, transformHint, currentMaxAcquiredBufferCount); } }; // Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see // clang warning -Wweak-vtables) BpTransactionCompletedListener::~BpTransactionCompletedListener() = default; IMPLEMENT_META_INTERFACE(TransactionCompletedListener, "android.gui.ITransactionComposerListener"); status_t BnTransactionCompletedListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast(Tag::LAST)) { return BBinder::onTransact(code, data, reply, flags); } auto tag = static_cast(code); switch (tag) { case Tag::ON_TRANSACTION_COMPLETED: return callLocalAsync(data, reply, &ITransactionCompletedListener::onTransactionCompleted); case Tag::ON_RELEASE_BUFFER: return callLocalAsync(data, reply, &ITransactionCompletedListener::onReleaseBuffer); } } ListenerCallbacks ListenerCallbacks::filter(CallbackId::Type type) const { std::vector filteredCallbackIds; for (const auto& callbackId : callbackIds) { if (callbackId.type == type) { filteredCallbackIds.push_back(callbackId); } } return ListenerCallbacks(transactionCompletedListener, filteredCallbackIds); } status_t CallbackId::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, id); SAFE_PARCEL(output->writeInt32, static_cast(type)); return NO_ERROR; } status_t CallbackId::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readInt64, &id); int32_t typeAsInt; SAFE_PARCEL(input->readInt32, &typeAsInt); type = static_cast(typeAsInt); return NO_ERROR; } status_t ReleaseCallbackId::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeUint64, bufferId); SAFE_PARCEL(output->writeUint64, framenumber); return NO_ERROR; } status_t ReleaseCallbackId::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readUint64, &bufferId); SAFE_PARCEL(input->readUint64, &framenumber); return NO_ERROR; } const ReleaseCallbackId ReleaseCallbackId::INVALID_ID = ReleaseCallbackId(0, 0); }; // namespace android