Loading libs/binder/rust/src/parcel/parcelable.rs +1 −0 Original line number Diff line number Diff line Loading @@ -866,6 +866,7 @@ impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { } } #[allow(dead_code)] struct AssertIBinder; impl Interface for AssertIBinder {} impl FromIBinder for AssertIBinder { Loading libs/binder/tests/binderAllocationLimits.cpp +40 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include <android-base/logging.h> #include <android/os/IServiceManager.h> #include <binder/Binder.h> #include <binder/Functional.h> #include <binder/IServiceManager.h> Loading Loading @@ -243,6 +244,45 @@ TEST(BinderAllocation, PingTransaction) { a_binder->pingBinder(); } // Return the max size of a string that will get the Small String Optimization // and avoid a heap allocation static size_t getSSOMaxSize() { size_t mallocs = 0; const auto on_malloc = OnMalloc([&](size_t /* bytes */) { mallocs++; }); for (int i = 1; true; i++) { std::string s(i, 'a'); if (mallocs) return i - 1; } } TEST(BinderAllocation, GetListOfStrings) { sp<android::os::IServiceManager> sm = android::interface_cast<android::os::IServiceManager>(GetRemoteBinder()); // 128 bytes Parcel::writeInterfaceToken -> writeInt32 (why 128 bytes?) // 9480 Parcel::readUtf8VectorFromUtf16Vector -> readData -> c->resize(9480) // then it's all readUtf8FromUtf16 calls from readUtf8VectorFromUtf16Vector // Parcel::readUtf8VectorFromUtf16Vector -> readData -> readUtf8FromUtf16 const size_t numExtraMallocs = 2; size_t mallocs = 0; // Could save a single malloc by starting with a large enough vector, // not worth doing without knowing the number of services. std::vector<std::string> ret; size_t maxSSOSize = getSSOMaxSize(); const auto on_malloc = OnMalloc([&](size_t /* bytes */) { mallocs++; }); ASSERT_TRUE(sm->listServices(android::IServiceManager::DUMP_FLAG_PRIORITY_ALL, &ret).isOk()); ASSERT_GT(ret.size(), 0u); size_t numStringAllocations = std::ranges::count_if(ret, [maxSSOSize](const std::string& s) { // In readUtf8FromUtf16 we resize with num chars + 1 return s.size() + 1 > maxSSOSize; }); EXPECT_EQ(mallocs, numStringAllocations + numExtraMallocs) << "Expecting " << numStringAllocations << " string allocs"; } TEST(BinderAllocation, MakeScopeGuard) { const auto m = ScopeDisallowMalloc(); { Loading libs/gui/BLASTBufferQueue.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -393,6 +393,13 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence mBufferItemConsumer->setTransformHint(mTransformHint); BQA_LOGV("updated mTransformHint=%d", mTransformHint); } if (stat.cornerRadii.has_value()) { BQA_LOGV("updated cornerRadii=%s", stat.cornerRadii.value().toString().c_str()); std::function<void(const gui::CornerRadii)> callbackCopy = getCornerRadiiCallback(); if (callbackCopy) callbackCopy(stat.cornerRadii.value()); } // Update frametime stamps if the frame was latched and presented, indicated by a // valid latch time. if (stat.latchTime > 0) { Loading Loading @@ -1383,6 +1390,17 @@ void BLASTBufferQueue::setApplyToken(sp<IBinder> applyToken) { mApplyToken = std::move(applyToken); } void BLASTBufferQueue::setCornerRadiiCallback( std::function<void(const gui::CornerRadii)> callback) { std::lock_guard _lock{mCornerRadiiCallbackMutex}; mCornerRadiiCallback = std::move(callback); } std::function<void(const gui::CornerRadii)> BLASTBufferQueue::getCornerRadiiCallback() const { std::lock_guard _lock{mCornerRadiiCallbackMutex}; return mCornerRadiiCallback; } void BLASTBufferQueue::setWaitForBufferReleaseCallback( std::function<void(const nsecs_t)> callback) { std::lock_guard _lock{mWaitForBufferReleaseMutex}; Loading libs/gui/BufferItem.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -245,7 +245,6 @@ status_t BufferItem::unflatten( uint32_t timestampLo = 0, timestampHi = 0; uint32_t frameNumberLo = 0, frameNumberHi = 0; int32_t pictureProfileIdLo = 0, pictureProfileIdHi = 0; readAligned(buffer, size, mCrop); readAligned(buffer, size, mTransform); Loading @@ -257,6 +256,7 @@ status_t BufferItem::unflatten( readAligned(buffer, size, mDataSpace); #if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES bool hasPictureProfileHandle; int32_t pictureProfileIdLo = 0, pictureProfileIdHi = 0; readAligned(buffer, size, hasPictureProfileHandle); readAligned(buffer, size, pictureProfileIdLo); readAligned(buffer, size, pictureProfileIdHi); Loading libs/gui/ITransactionCompletedListener.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,10 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { } SAFE_PARCEL(output->writeUint32, currentMaxAcquiredBufferCount); SAFE_PARCEL(output->writeBool, cornerRadii.has_value()); if (cornerRadii.has_value()) { SAFE_PARCEL(output->writeParcelable, cornerRadii.value()); } SAFE_PARCEL(output->writeParcelable, eventStats); SAFE_PARCEL(output->writeParcelable, previousReleaseCallbackId); return NO_ERROR; Loading Loading @@ -171,6 +175,16 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) { } SAFE_PARCEL(input->readUint32, ¤tMaxAcquiredBufferCount); bool hasCornerRadii = false; SAFE_PARCEL(input->readBool, &hasCornerRadii); if (hasCornerRadii) { gui::CornerRadii tempRadii; SAFE_PARCEL(input->readParcelable, &tempRadii); cornerRadii = std::make_optional(tempRadii); } else { cornerRadii = std::nullopt; } SAFE_PARCEL(input->readParcelable, &eventStats); SAFE_PARCEL(input->readParcelable, &previousReleaseCallbackId); Loading Loading
libs/binder/rust/src/parcel/parcelable.rs +1 −0 Original line number Diff line number Diff line Loading @@ -866,6 +866,7 @@ impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { } } #[allow(dead_code)] struct AssertIBinder; impl Interface for AssertIBinder {} impl FromIBinder for AssertIBinder { Loading
libs/binder/tests/binderAllocationLimits.cpp +40 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include <android-base/logging.h> #include <android/os/IServiceManager.h> #include <binder/Binder.h> #include <binder/Functional.h> #include <binder/IServiceManager.h> Loading Loading @@ -243,6 +244,45 @@ TEST(BinderAllocation, PingTransaction) { a_binder->pingBinder(); } // Return the max size of a string that will get the Small String Optimization // and avoid a heap allocation static size_t getSSOMaxSize() { size_t mallocs = 0; const auto on_malloc = OnMalloc([&](size_t /* bytes */) { mallocs++; }); for (int i = 1; true; i++) { std::string s(i, 'a'); if (mallocs) return i - 1; } } TEST(BinderAllocation, GetListOfStrings) { sp<android::os::IServiceManager> sm = android::interface_cast<android::os::IServiceManager>(GetRemoteBinder()); // 128 bytes Parcel::writeInterfaceToken -> writeInt32 (why 128 bytes?) // 9480 Parcel::readUtf8VectorFromUtf16Vector -> readData -> c->resize(9480) // then it's all readUtf8FromUtf16 calls from readUtf8VectorFromUtf16Vector // Parcel::readUtf8VectorFromUtf16Vector -> readData -> readUtf8FromUtf16 const size_t numExtraMallocs = 2; size_t mallocs = 0; // Could save a single malloc by starting with a large enough vector, // not worth doing without knowing the number of services. std::vector<std::string> ret; size_t maxSSOSize = getSSOMaxSize(); const auto on_malloc = OnMalloc([&](size_t /* bytes */) { mallocs++; }); ASSERT_TRUE(sm->listServices(android::IServiceManager::DUMP_FLAG_PRIORITY_ALL, &ret).isOk()); ASSERT_GT(ret.size(), 0u); size_t numStringAllocations = std::ranges::count_if(ret, [maxSSOSize](const std::string& s) { // In readUtf8FromUtf16 we resize with num chars + 1 return s.size() + 1 > maxSSOSize; }); EXPECT_EQ(mallocs, numStringAllocations + numExtraMallocs) << "Expecting " << numStringAllocations << " string allocs"; } TEST(BinderAllocation, MakeScopeGuard) { const auto m = ScopeDisallowMalloc(); { Loading
libs/gui/BLASTBufferQueue.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -393,6 +393,13 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence mBufferItemConsumer->setTransformHint(mTransformHint); BQA_LOGV("updated mTransformHint=%d", mTransformHint); } if (stat.cornerRadii.has_value()) { BQA_LOGV("updated cornerRadii=%s", stat.cornerRadii.value().toString().c_str()); std::function<void(const gui::CornerRadii)> callbackCopy = getCornerRadiiCallback(); if (callbackCopy) callbackCopy(stat.cornerRadii.value()); } // Update frametime stamps if the frame was latched and presented, indicated by a // valid latch time. if (stat.latchTime > 0) { Loading Loading @@ -1383,6 +1390,17 @@ void BLASTBufferQueue::setApplyToken(sp<IBinder> applyToken) { mApplyToken = std::move(applyToken); } void BLASTBufferQueue::setCornerRadiiCallback( std::function<void(const gui::CornerRadii)> callback) { std::lock_guard _lock{mCornerRadiiCallbackMutex}; mCornerRadiiCallback = std::move(callback); } std::function<void(const gui::CornerRadii)> BLASTBufferQueue::getCornerRadiiCallback() const { std::lock_guard _lock{mCornerRadiiCallbackMutex}; return mCornerRadiiCallback; } void BLASTBufferQueue::setWaitForBufferReleaseCallback( std::function<void(const nsecs_t)> callback) { std::lock_guard _lock{mWaitForBufferReleaseMutex}; Loading
libs/gui/BufferItem.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -245,7 +245,6 @@ status_t BufferItem::unflatten( uint32_t timestampLo = 0, timestampHi = 0; uint32_t frameNumberLo = 0, frameNumberHi = 0; int32_t pictureProfileIdLo = 0, pictureProfileIdHi = 0; readAligned(buffer, size, mCrop); readAligned(buffer, size, mTransform); Loading @@ -257,6 +256,7 @@ status_t BufferItem::unflatten( readAligned(buffer, size, mDataSpace); #if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES bool hasPictureProfileHandle; int32_t pictureProfileIdLo = 0, pictureProfileIdHi = 0; readAligned(buffer, size, hasPictureProfileHandle); readAligned(buffer, size, pictureProfileIdLo); readAligned(buffer, size, pictureProfileIdHi); Loading
libs/gui/ITransactionCompletedListener.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,10 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { } SAFE_PARCEL(output->writeUint32, currentMaxAcquiredBufferCount); SAFE_PARCEL(output->writeBool, cornerRadii.has_value()); if (cornerRadii.has_value()) { SAFE_PARCEL(output->writeParcelable, cornerRadii.value()); } SAFE_PARCEL(output->writeParcelable, eventStats); SAFE_PARCEL(output->writeParcelable, previousReleaseCallbackId); return NO_ERROR; Loading Loading @@ -171,6 +175,16 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) { } SAFE_PARCEL(input->readUint32, ¤tMaxAcquiredBufferCount); bool hasCornerRadii = false; SAFE_PARCEL(input->readBool, &hasCornerRadii); if (hasCornerRadii) { gui::CornerRadii tempRadii; SAFE_PARCEL(input->readParcelable, &tempRadii); cornerRadii = std::make_optional(tempRadii); } else { cornerRadii = std::nullopt; } SAFE_PARCEL(input->readParcelable, &eventStats); SAFE_PARCEL(input->readParcelable, &previousReleaseCallbackId); Loading