Loading libs/binder/Binder.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ #endif #include "BuildFlags.h" #include "Constants.h" #include "OS.h" #include "RpcState.h" Loading Loading @@ -70,8 +71,6 @@ constexpr bool kEnableRecording = true; constexpr bool kEnableRecording = false; #endif // Log any reply transactions for which the data exceeds this size #define LOG_REPLIES_OVER_SIZE (300 * 1024) // --------------------------------------------------------------------------- IBinder::IBinder() Loading Loading @@ -412,7 +411,7 @@ status_t BBinder::transact( // In case this is being transacted on in the same process. if (reply != nullptr) { reply->setDataPosition(0); if (reply->dataSize() > LOG_REPLIES_OVER_SIZE) { if (reply->dataSize() > binder::kLogTransactionsOverBytes) { ALOGW("Large reply transaction of %zu bytes, interface descriptor %s, code %d", reply->dataSize(), String8(getInterfaceDescriptor()).c_str(), code); } Loading libs/binder/BpBinder.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <stdio.h> #include "BuildFlags.h" #include "Constants.h" #include "file.h" //#undef ALOGV Loading Loading @@ -63,9 +64,6 @@ std::atomic<uint32_t> BpBinder::sBinderProxyCountWarned(0); static constexpr uint32_t kBinderProxyCountWarnInterval = 5000; // Log any transactions for which the data exceeds this size #define LOG_TRANSACTIONS_OVER_SIZE (300 * 1024) enum { LIMIT_REACHED_MASK = 0x80000000, // A flag denoting that the limit has been reached WARNING_REACHED_MASK = 0x40000000, // A flag denoting that the warning has been reached Loading Loading @@ -403,9 +401,11 @@ status_t BpBinder::transact( status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags); } if (data.dataSize() > LOG_TRANSACTIONS_OVER_SIZE) { if (data.dataSize() > binder::kLogTransactionsOverBytes) { RpcMutexUniqueLock _l(mLock); ALOGW("Large outgoing transaction of %zu bytes, interface descriptor %s, code %d", ALOGW("Large outgoing transaction of %zu bytes, interface descriptor %s, code %d was " "sent", data.dataSize(), String8(mDescriptorCache).c_str(), code); } Loading libs/binder/Constants.h 0 → 100644 +39 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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. */ #pragma once namespace android::binder { /** * See also BINDER_VM_SIZE. In kernel binder, the sum of all transactions must be allocated in this * space. Large transactions are very error prone. In general, we should work to reduce this limit. * The same limit is used in RPC binder for consistency. */ constexpr size_t kLogTransactionsOverBytes = 300 * 1024; /** * See b/392575419 - this limit is chosen for a specific usecase, because RPC binder does not have * support for shared memory in the Android Baklava timeframe. This was 100 KB during and before * Android V. * * Keeping this low helps preserve overall system performance. Transactions of this size are far too * expensive to make multiple copies over binder or sockets, and they should be avoided if at all * possible and transition to shared memory. */ constexpr size_t kRpcTransactionLimitBytes = 600 * 1024; } // namespace android::binder libs/binder/RpcState.cpp +7 −4 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <binder/IPCThreadState.h> #include <binder/RpcServer.h> #include "Constants.h" #include "Debug.h" #include "RpcWireFormat.h" #include "Utils.h" Loading Loading @@ -337,6 +338,8 @@ std::string RpcState::BinderNode::toString() const { } RpcState::CommandData::CommandData(size_t size) : mSize(size) { if (size == 0) return; // The maximum size for regular binder is 1MB for all concurrent // transactions. A very small proportion of transactions are even // larger than a page, but we need to avoid allocating too much Loading @@ -348,11 +351,11 @@ RpcState::CommandData::CommandData(size_t size) : mSize(size) { // transaction (in some cases, additional fixed size amounts are added), // though for rough consistency, we should avoid cases where this data type // is used for multiple dynamic allocations for a single transaction. constexpr size_t kMaxTransactionAllocation = 100 * 1000; if (size == 0) return; if (size > kMaxTransactionAllocation) { ALOGW("Transaction requested too much data allocation %zu", size); if (size > binder::kRpcTransactionLimitBytes) { ALOGE("Transaction requested too much data allocation: %zu bytes, failing.", size); return; } else if (size > binder::kLogTransactionsOverBytes) { ALOGW("Transaction too large: inefficient and in danger of breaking: %zu bytes.", size); } mData.reset(new (std::nothrow) uint8_t[size]); } Loading libs/binder/tests/IBinderRpcTest.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ interface IBinderRpcTest { void holdBinder(@nullable IBinder binder); @nullable IBinder getHeldBinder(); byte[] repeatBytes(in byte[] bytes); // Idea is client creates its own instance of IBinderRpcTest and calls this, // and the server calls 'binder' with (calls - 1) passing itself as 'binder', // going back and forth until calls = 0 Loading Loading
libs/binder/Binder.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ #endif #include "BuildFlags.h" #include "Constants.h" #include "OS.h" #include "RpcState.h" Loading Loading @@ -70,8 +71,6 @@ constexpr bool kEnableRecording = true; constexpr bool kEnableRecording = false; #endif // Log any reply transactions for which the data exceeds this size #define LOG_REPLIES_OVER_SIZE (300 * 1024) // --------------------------------------------------------------------------- IBinder::IBinder() Loading Loading @@ -412,7 +411,7 @@ status_t BBinder::transact( // In case this is being transacted on in the same process. if (reply != nullptr) { reply->setDataPosition(0); if (reply->dataSize() > LOG_REPLIES_OVER_SIZE) { if (reply->dataSize() > binder::kLogTransactionsOverBytes) { ALOGW("Large reply transaction of %zu bytes, interface descriptor %s, code %d", reply->dataSize(), String8(getInterfaceDescriptor()).c_str(), code); } Loading
libs/binder/BpBinder.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <stdio.h> #include "BuildFlags.h" #include "Constants.h" #include "file.h" //#undef ALOGV Loading Loading @@ -63,9 +64,6 @@ std::atomic<uint32_t> BpBinder::sBinderProxyCountWarned(0); static constexpr uint32_t kBinderProxyCountWarnInterval = 5000; // Log any transactions for which the data exceeds this size #define LOG_TRANSACTIONS_OVER_SIZE (300 * 1024) enum { LIMIT_REACHED_MASK = 0x80000000, // A flag denoting that the limit has been reached WARNING_REACHED_MASK = 0x40000000, // A flag denoting that the warning has been reached Loading Loading @@ -403,9 +401,11 @@ status_t BpBinder::transact( status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags); } if (data.dataSize() > LOG_TRANSACTIONS_OVER_SIZE) { if (data.dataSize() > binder::kLogTransactionsOverBytes) { RpcMutexUniqueLock _l(mLock); ALOGW("Large outgoing transaction of %zu bytes, interface descriptor %s, code %d", ALOGW("Large outgoing transaction of %zu bytes, interface descriptor %s, code %d was " "sent", data.dataSize(), String8(mDescriptorCache).c_str(), code); } Loading
libs/binder/Constants.h 0 → 100644 +39 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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. */ #pragma once namespace android::binder { /** * See also BINDER_VM_SIZE. In kernel binder, the sum of all transactions must be allocated in this * space. Large transactions are very error prone. In general, we should work to reduce this limit. * The same limit is used in RPC binder for consistency. */ constexpr size_t kLogTransactionsOverBytes = 300 * 1024; /** * See b/392575419 - this limit is chosen for a specific usecase, because RPC binder does not have * support for shared memory in the Android Baklava timeframe. This was 100 KB during and before * Android V. * * Keeping this low helps preserve overall system performance. Transactions of this size are far too * expensive to make multiple copies over binder or sockets, and they should be avoided if at all * possible and transition to shared memory. */ constexpr size_t kRpcTransactionLimitBytes = 600 * 1024; } // namespace android::binder
libs/binder/RpcState.cpp +7 −4 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <binder/IPCThreadState.h> #include <binder/RpcServer.h> #include "Constants.h" #include "Debug.h" #include "RpcWireFormat.h" #include "Utils.h" Loading Loading @@ -337,6 +338,8 @@ std::string RpcState::BinderNode::toString() const { } RpcState::CommandData::CommandData(size_t size) : mSize(size) { if (size == 0) return; // The maximum size for regular binder is 1MB for all concurrent // transactions. A very small proportion of transactions are even // larger than a page, but we need to avoid allocating too much Loading @@ -348,11 +351,11 @@ RpcState::CommandData::CommandData(size_t size) : mSize(size) { // transaction (in some cases, additional fixed size amounts are added), // though for rough consistency, we should avoid cases where this data type // is used for multiple dynamic allocations for a single transaction. constexpr size_t kMaxTransactionAllocation = 100 * 1000; if (size == 0) return; if (size > kMaxTransactionAllocation) { ALOGW("Transaction requested too much data allocation %zu", size); if (size > binder::kRpcTransactionLimitBytes) { ALOGE("Transaction requested too much data allocation: %zu bytes, failing.", size); return; } else if (size > binder::kLogTransactionsOverBytes) { ALOGW("Transaction too large: inefficient and in danger of breaking: %zu bytes.", size); } mData.reset(new (std::nothrow) uint8_t[size]); } Loading
libs/binder/tests/IBinderRpcTest.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ interface IBinderRpcTest { void holdBinder(@nullable IBinder binder); @nullable IBinder getHeldBinder(); byte[] repeatBytes(in byte[] bytes); // Idea is client creates its own instance of IBinderRpcTest and calls this, // and the server calls 'binder' with (calls - 1) passing itself as 'binder', // going back and forth until calls = 0 Loading