Merge "libbinder: cache interface descriptor if empty" am: 6f69c67d9f
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/2365608
Change-Id: Ifcf5eb92114787c8ea0ad3410791ad6a6181ffab
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 54d2445..1c470a1 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -47,6 +47,8 @@
binder_proxy_limit_callback BpBinder::sLimitCallback;
bool BpBinder::sBinderProxyThrottleCreate = false;
+static StaticString16 kDescriptorUninit(u"<uninit descriptor>");
+
// Arbitrarily high value that probably distinguishes a bad behaving app
uint32_t BpBinder::sBinderProxyCountHighWatermark = 2500;
// Another arbitrary value a binder count needs to drop below before another callback will be called
@@ -211,6 +213,7 @@
mAlive(true),
mObitsSent(false),
mObituaries(nullptr),
+ mDescriptorCache(kDescriptorUninit),
mTrackedUid(-1) {
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
}
@@ -258,12 +261,12 @@
bool BpBinder::isDescriptorCached() const {
Mutex::Autolock _l(mLock);
- return mDescriptorCache.size() ? true : false;
+ return mDescriptorCache.string() != kDescriptorUninit.string();
}
const String16& BpBinder::getInterfaceDescriptor() const
{
- if (isDescriptorCached() == false) {
+ if (!isDescriptorCached()) {
sp<BpBinder> thiz = sp<BpBinder>::fromExisting(const_cast<BpBinder*>(this));
Parcel data;
@@ -276,8 +279,7 @@
Mutex::Autolock _l(mLock);
// mDescriptorCache could have been assigned while the lock was
// released.
- if (mDescriptorCache.size() == 0)
- mDescriptorCache = res;
+ if (mDescriptorCache.string() == kDescriptorUninit.string()) mDescriptorCache = res;
}
}
@@ -369,10 +371,7 @@
if (data.dataSize() > LOG_TRANSACTIONS_OVER_SIZE) {
Mutex::Autolock _l(mLock);
ALOGW("Large outgoing transaction of %zu bytes, interface descriptor %s, code %d",
- data.dataSize(),
- mDescriptorCache.size() ? String8(mDescriptorCache).c_str()
- : "<uncached descriptor>",
- code);
+ data.dataSize(), String8(mDescriptorCache).c_str(), code);
}
if (status == DEAD_OBJECT) mAlive = 0;
@@ -647,7 +646,7 @@
if(obits != nullptr) {
if (!obits->isEmpty()) {
ALOGI("onLastStrongRef automatically unlinking death recipients: %s",
- mDescriptorCache.size() ? String8(mDescriptorCache).c_str() : "<uncached descriptor>");
+ String8(mDescriptorCache).c_str());
}
if (ipc) ipc->clearDeathNotification(binderHandle(), this);
diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp
index 55a3916..6a6e008 100644
--- a/libs/binder/tests/binderAllocationLimits.cpp
+++ b/libs/binder/tests/binderAllocationLimits.cpp
@@ -172,6 +172,24 @@
a_binder->pingBinder();
}
+TEST(BinderAllocation, InterfaceDescriptorTransaction) {
+ sp<IBinder> a_binder = GetRemoteBinder();
+
+ size_t mallocs = 0;
+ const auto on_malloc = OnMalloc([&](size_t bytes) {
+ mallocs++;
+ // Happens to be SM package length. We could switch to forking
+ // and registering our own service if it became an issue.
+ EXPECT_EQ(bytes, 78);
+ });
+
+ a_binder->getInterfaceDescriptor();
+ a_binder->getInterfaceDescriptor();
+ a_binder->getInterfaceDescriptor();
+
+ EXPECT_EQ(mallocs, 1);
+}
+
TEST(BinderAllocation, SmallTransaction) {
String16 empty_descriptor = String16("");
sp<IServiceManager> manager = defaultServiceManager();