Merge changes I021be9a3,Ia11839d1
* changes:
LayerTraceGenerator: Fix layer deletion
LayerTraceGenerator: Fix duplicate layer ids
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index a2491e5..a60972b 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -101,6 +101,7 @@
"libhidlbase",
"liblog",
"libutils",
+ "libvintf",
"libbinderdebug",
"packagemanager_aidl-cpp",
],
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 0d05116..942a17e 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -88,6 +88,7 @@
#include <private/android_logger.h>
#include <serviceutils/PriorityDumper.h>
#include <utils/StrongPointer.h>
+#include <vintf/VintfObject.h>
#include "DumpstateInternal.h"
#include "DumpstateService.h"
#include "dumpstate.h"
@@ -1396,6 +1397,23 @@
}
}
+// Dump all of the files that make up the vendor interface.
+// See the files listed in dumpFileList() for the latest list of files.
+static void DumpVintf() {
+ const auto vintfFiles = android::vintf::details::dumpFileList();
+ for (const auto vintfFile : vintfFiles) {
+ struct stat st;
+ if (stat(vintfFile.c_str(), &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ ds.AddDir(vintfFile, true /* recursive */);
+ } else {
+ ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
+ vintfFile);
+ }
+ }
+ }
+}
+
static void DumpExternalFragmentationInfo() {
struct stat st;
if (stat("/proc/buddyinfo", &st) != 0) {
@@ -1621,6 +1639,8 @@
do_dmesg();
}
+ DumpVintf();
+
RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
diff --git a/include/input/Input.h b/include/input/Input.h
index 693f68a..e0c9de4 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -1061,35 +1061,44 @@
/* Pointer icon styles.
* Must match the definition in android.view.PointerIcon.
+ *
+ * Due to backwards compatibility and public api constraints, this is a duplicate (but type safe)
+ * definition of PointerIcon.java.
+ *
+ * TODO(b/235023317) move this definition to an aidl and statically assign to the below java public
+ * api values.
+ *
+ * WARNING: Keep these definitions in sync with
+ * frameworks/base/core/java/android/view/PointerIcon.java
*/
-enum {
- POINTER_ICON_STYLE_CUSTOM = -1,
- POINTER_ICON_STYLE_NULL = 0,
- POINTER_ICON_STYLE_ARROW = 1000,
- POINTER_ICON_STYLE_CONTEXT_MENU = 1001,
- POINTER_ICON_STYLE_HAND = 1002,
- POINTER_ICON_STYLE_HELP = 1003,
- POINTER_ICON_STYLE_WAIT = 1004,
- POINTER_ICON_STYLE_CELL = 1006,
- POINTER_ICON_STYLE_CROSSHAIR = 1007,
- POINTER_ICON_STYLE_TEXT = 1008,
- POINTER_ICON_STYLE_VERTICAL_TEXT = 1009,
- POINTER_ICON_STYLE_ALIAS = 1010,
- POINTER_ICON_STYLE_COPY = 1011,
- POINTER_ICON_STYLE_NO_DROP = 1012,
- POINTER_ICON_STYLE_ALL_SCROLL = 1013,
- POINTER_ICON_STYLE_HORIZONTAL_DOUBLE_ARROW = 1014,
- POINTER_ICON_STYLE_VERTICAL_DOUBLE_ARROW = 1015,
- POINTER_ICON_STYLE_TOP_RIGHT_DOUBLE_ARROW = 1016,
- POINTER_ICON_STYLE_TOP_LEFT_DOUBLE_ARROW = 1017,
- POINTER_ICON_STYLE_ZOOM_IN = 1018,
- POINTER_ICON_STYLE_ZOOM_OUT = 1019,
- POINTER_ICON_STYLE_GRAB = 1020,
- POINTER_ICON_STYLE_GRABBING = 1021,
+enum class PointerIconStyle : int32_t {
+ TYPE_CUSTOM = -1,
+ TYPE_NULL = 0,
+ TYPE_ARROW = 1000,
+ TYPE_CONTEXT_MENU = 1001,
+ TYPE_HAND = 1002,
+ TYPE_HELP = 1003,
+ TYPE_WAIT = 1004,
+ TYPE_CELL = 1006,
+ TYPE_CROSSHAIR = 1007,
+ TYPE_TEXT = 1008,
+ TYPE_VERTICAL_TEXT = 1009,
+ TYPE_ALIAS = 1010,
+ TYPE_COPY = 1011,
+ TYPE_NO_DROP = 1012,
+ TYPE_ALL_SCROLL = 1013,
+ TYPE_HORIZONTAL_DOUBLE_ARROW = 1014,
+ TYPE_VERTICAL_DOUBLE_ARROW = 1015,
+ TYPE_TOP_RIGHT_DOUBLE_ARROW = 1016,
+ TYPE_TOP_LEFT_DOUBLE_ARROW = 1017,
+ TYPE_ZOOM_IN = 1018,
+ TYPE_ZOOM_OUT = 1019,
+ TYPE_GRAB = 1020,
+ TYPE_GRABBING = 1021,
- POINTER_ICON_STYLE_SPOT_HOVER = 2000,
- POINTER_ICON_STYLE_SPOT_TOUCH = 2001,
- POINTER_ICON_STYLE_SPOT_ANCHOR = 2002,
+ TYPE_SPOT_HOVER = 2000,
+ TYPE_SPOT_TOUCH = 2001,
+ TYPE_SPOT_ANCHOR = 2002,
};
} // namespace android
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 6a12e65..e2db1a3 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -32,9 +32,12 @@
#include <utils/misc.h>
#include <inttypes.h>
-#include <linux/sched.h>
#include <stdio.h>
+#ifdef __linux__
+#include <linux/sched.h>
+#endif
+
#include "RpcState.h"
namespace android {
@@ -234,11 +237,13 @@
{
public:
// unlocked objects
- bool mRequestingSid = false;
- bool mInheritRt = false;
sp<IBinder> mExtension;
+#ifdef __linux__
int mPolicy = SCHED_NORMAL;
int mPriority = 0;
+#endif
+ bool mRequestingSid = false;
+ bool mInheritRt = false;
// for below objects
Mutex mLock;
@@ -407,6 +412,7 @@
return e->mExtension;
}
+#ifdef __linux__
void BBinder::setMinSchedulerPolicy(int policy, int priority) {
LOG_ALWAYS_FATAL_IF(mParceled,
"setMinSchedulerPolicy() should not be called after a binder object "
@@ -451,6 +457,7 @@
if (e == nullptr) return 0;
return e->mPriority;
}
+#endif // __linux__
bool BBinder::isInheritRt() {
Extras* e = mExtras.load(std::memory_order_acquire);
@@ -478,7 +485,12 @@
}
pid_t BBinder::getDebugPid() {
+#ifdef __linux__
return getpid();
+#else
+ // TODO: handle other OSes
+ return 0;
+#endif // __linux__
}
void BBinder::setExtension(const sp<IBinder>& extension) {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 038ce38..e67dd7b 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -87,7 +87,8 @@
static std::atomic<size_t> gParcelGlobalAllocCount;
static std::atomic<size_t> gParcelGlobalAllocSize;
-static size_t gMaxFds = 0;
+// Maximum number of file descriptors per Parcel.
+constexpr size_t kMaxFds = 1024;
// Maximum size of a blob to transfer in-place.
static const size_t BLOB_INPLACE_LIMIT = 16 * 1024;
@@ -1416,7 +1417,7 @@
const size_t len = val.getFlattenedSize();
const size_t fd_count = val.getFdCount();
- if ((len > INT32_MAX) || (fd_count >= gMaxFds)) {
+ if ((len > INT32_MAX) || (fd_count > kMaxFds)) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
return BAD_VALUE;
@@ -2158,7 +2159,7 @@
const size_t len = this->readInt32();
const size_t fd_count = this->readInt32();
- if ((len > INT32_MAX) || (fd_count >= gMaxFds)) {
+ if ((len > INT32_MAX) || (fd_count > kMaxFds)) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
return BAD_VALUE;
@@ -2747,18 +2748,6 @@
mAllowFds = true;
mDeallocZero = false;
mOwner = nullptr;
-
- // racing multiple init leads only to multiple identical write
- if (gMaxFds == 0) {
- struct rlimit result;
- if (!getrlimit(RLIMIT_NOFILE, &result)) {
- gMaxFds = (size_t)result.rlim_cur;
- //ALOGI("parcel fd limit set to %zu", gMaxFds);
- } else {
- ALOGW("Unable to getrlimit: %s", strerror(errno));
- gMaxFds = 1024;
- }
- }
}
void Parcel::scanForFds() const {
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index c67b70a..528341e 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -135,7 +135,7 @@
mRootObjectWeak = binder;
}
void RpcServer::setPerSessionRootObject(
- std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& makeObject) {
+ std::function<sp<IBinder>(const void*, size_t)>&& makeObject) {
std::lock_guard<std::mutex> _l(mLock);
mRootObject.clear();
mRootObjectWeak.clear();
@@ -178,14 +178,16 @@
status_t status;
while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) {
- sockaddr_storage addr;
- socklen_t addrLen = sizeof(addr);
+ std::array<uint8_t, kRpcAddressSize> addr;
+ static_assert(addr.size() >= sizeof(sockaddr_storage), "kRpcAddressSize is too small");
+ socklen_t addrLen = addr.size();
unique_fd clientFd(
- TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(&addr),
+ TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(addr.data()),
&addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK)));
- LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(addr)), "Truncated address");
+ LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(sockaddr_storage)),
+ "Truncated address");
if (clientFd < 0) {
ALOGE("Could not accept4 socket: %s", strerror(errno));
@@ -268,7 +270,7 @@
}
void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
- const sockaddr_storage addr, socklen_t addrLen) {
+ std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen) {
// mShutdownTrigger can only be cleared once connection threads have joined.
// It must be set before this thread is started
LOG_ALWAYS_FATAL_IF(server->mShutdownTrigger == nullptr);
@@ -390,16 +392,14 @@
}
} while (server->mSessions.end() != server->mSessions.find(sessionId));
- session = RpcSession::make();
+ session = sp<RpcSession>::make(nullptr);
session->setMaxIncomingThreads(server->mMaxThreads);
if (!session->setProtocolVersion(protocolVersion)) return;
// if null, falls back to server root
sp<IBinder> sessionSpecificRoot;
if (server->mRootObjectFactory != nullptr) {
- sessionSpecificRoot =
- server->mRootObjectFactory(reinterpret_cast<const sockaddr*>(&addr),
- addrLen);
+ sessionSpecificRoot = server->mRootObjectFactory(addr.data(), addrLen);
if (sessionSpecificRoot == nullptr) {
ALOGE("Warning: server returned null from root object factory");
}
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 5c35dd0..8edc78f 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -715,6 +715,7 @@
LOG_ALWAYS_FATAL_IF(mEventListener != nullptr);
LOG_ALWAYS_FATAL_IF(eventListener == nullptr);
LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr);
+ LOG_ALWAYS_FATAL_IF(mCtx != nullptr);
mShutdownTrigger = FdTrigger::make();
if (mShutdownTrigger == nullptr) return false;
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index f16a9ab..f5de5b1 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -964,23 +964,19 @@
const sp<RpcSession>& session, const RpcWireHeader& command) {
LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_DEC_STRONG, "command: %d", command.command);
- CommandData commandData(command.bodySize);
- if (!commandData.valid()) {
- return NO_MEMORY;
- }
- iovec iov{commandData.data(), commandData.size()};
- if (status_t status = rpcRec(connection, session, "dec ref body", &iov, 1); status != OK)
- return status;
-
if (command.bodySize != sizeof(RpcDecStrong)) {
ALOGE("Expecting %zu but got %" PRId32 " bytes for RpcDecStrong. Terminating!",
sizeof(RpcDecStrong), command.bodySize);
(void)session->shutdownAndWait(false);
return BAD_VALUE;
}
- RpcDecStrong* body = reinterpret_cast<RpcDecStrong*>(commandData.data());
- uint64_t addr = RpcWireAddress::toRaw(body->address);
+ RpcDecStrong body;
+ iovec iov{&body, sizeof(RpcDecStrong)};
+ if (status_t status = rpcRec(connection, session, "dec ref body", &iov, 1); status != OK)
+ return status;
+
+ uint64_t addr = RpcWireAddress::toRaw(body.address);
std::unique_lock<std::mutex> _l(mNodeMutex);
auto it = mNodeForAddress.find(addr);
if (it == mNodeForAddress.end()) {
@@ -998,19 +994,19 @@
return BAD_VALUE;
}
- if (it->second.timesSent < body->amount) {
+ if (it->second.timesSent < body.amount) {
ALOGE("Record of sending binder %zu times, but requested decStrong for %" PRIu64 " of %u",
- it->second.timesSent, addr, body->amount);
+ it->second.timesSent, addr, body.amount);
return OK;
}
LOG_ALWAYS_FATAL_IF(it->second.sentRef == nullptr, "Inconsistent state, lost ref for %" PRIu64,
addr);
- LOG_RPC_DETAIL("Processing dec strong of %" PRIu64 " by %u from %zu", addr, body->amount,
+ LOG_RPC_DETAIL("Processing dec strong of %" PRIu64 " by %u from %zu", addr, body.amount,
it->second.timesSent);
- it->second.timesSent -= body->amount;
+ it->second.timesSent -= body.amount;
sp<IBinder> tempHold = tryEraseNode(it);
_l.unlock();
tempHold = nullptr; // destructor may make binder calls on this session
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 83b97d0..dba6587 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -139,6 +139,9 @@
mMessage = String8(message.value_or(String16()));
// Skip over the remote stack trace data
+ const size_t remote_start = parcel.dataPosition();
+ // Get available size before reading more
+ const size_t remote_avail = parcel.dataAvail();
int32_t remote_stack_trace_header_size;
status = parcel.readInt32(&remote_stack_trace_header_size);
if (status != OK) {
@@ -146,13 +149,16 @@
return status;
}
if (remote_stack_trace_header_size < 0 ||
- static_cast<size_t>(remote_stack_trace_header_size) > parcel.dataAvail()) {
+ static_cast<size_t>(remote_stack_trace_header_size) > remote_avail) {
android_errorWriteLog(0x534e4554, "132650049");
setFromStatusT(UNKNOWN_ERROR);
return UNKNOWN_ERROR;
}
- parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
+
+ if (remote_stack_trace_header_size != 0) {
+ parcel.setDataPosition(remote_start + remote_stack_trace_header_size);
+ }
if (mException == EX_SERVICE_SPECIFIC) {
status = parcel.readInt32(&mErrorCode);
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 6b31812..dba8dd6 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -125,9 +125,17 @@
*/
void setRootObjectWeak(const wp<IBinder>& binder);
/**
- * Allows a root object to be created for each session
+ * Allows a root object to be created for each session.
+ *
+ * Takes one argument: a callable that is invoked once per new session.
+ * The callable takes two arguments: a type-erased pointer to an OS- and
+ * transport-specific address structure, e.g., sockaddr_vm for vsock, and
+ * an integer representing the size in bytes of that structure. The
+ * callable should validate the size, then cast the type-erased pointer
+ * to a pointer to the actual type of the address, e.g., const void* to
+ * const sockaddr_vm*.
*/
- void setPerSessionRootObject(std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& object);
+ void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object);
sp<IBinder> getRootObject();
/**
@@ -177,8 +185,9 @@
void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override;
void onSessionIncomingThreadEnded() override;
+ static constexpr size_t kRpcAddressSize = 128;
static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
- const sockaddr_storage addr, socklen_t addrLen);
+ std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen);
[[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address);
const std::unique_ptr<RpcTransportCtx> mCtx;
@@ -192,7 +201,7 @@
std::map<std::thread::id, std::thread> mConnectingThreads;
sp<IBinder> mRootObject;
wp<IBinder> mRootObjectWeak;
- std::function<sp<IBinder>(const sockaddr*, socklen_t)> mRootObjectFactory;
+ std::function<sp<IBinder>(const void*, size_t)> mRootObjectFactory;
std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
std::unique_ptr<FdTrigger> mShutdownTrigger;
std::condition_variable mShutdownCv;
diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp
index bf2b25b..a3d42b7 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -38,10 +38,10 @@
<< " error: " << statusToString(status).c_str();
return false;
}
- server->setPerSessionRootObject([=](const sockaddr* addr, socklen_t addrlen) {
- LOG_ALWAYS_FATAL_IF(addr->sa_family != AF_VSOCK, "address is not a vsock");
+ server->setPerSessionRootObject([=](const void* addr, size_t addrlen) {
LOG_ALWAYS_FATAL_IF(addrlen < sizeof(sockaddr_vm), "sockaddr is truncated");
const sockaddr_vm* vaddr = reinterpret_cast<const sockaddr_vm*>(addr);
+ LOG_ALWAYS_FATAL_IF(vaddr->svm_family != AF_VSOCK, "address is not a vsock");
return AIBinder_toPlatformBinder(factory(vaddr->svm_cid, factoryContext));
});
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 28e3ff4..b21a7e9 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -36,6 +36,7 @@
using ::android::Parcel;
using ::android::sp;
using ::android::status_t;
+using ::android::statusToString;
using ::android::String16;
using ::android::String8;
using ::android::wp;
@@ -133,7 +134,8 @@
} else {
// b/155793159
LOG(ERROR) << __func__ << ": Cannot associate class '" << newDescriptor
- << "' to dead binder.";
+ << "' to dead binder with cached descriptor '" << SanitizeString(descriptor)
+ << "'.";
}
return false;
}
@@ -458,7 +460,8 @@
status_t status = binder->unlinkToDeath(recipient, cookie, 0 /*flags*/);
if (status != ::android::OK) {
LOG(ERROR) << __func__
- << ": removed reference to death recipient but unlink failed.";
+ << ": removed reference to death recipient but unlink failed: "
+ << statusToString(status);
}
return PruneStatusT(status);
}
@@ -539,7 +542,8 @@
binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
void* cookie) {
if (binder == nullptr || recipient == nullptr) {
- LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
+ LOG(ERROR) << __func__ << ": Must provide binder (" << binder << ") and recipient ("
+ << recipient << ")";
return STATUS_UNEXPECTED_NULL;
}
@@ -550,7 +554,8 @@
binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
void* cookie) {
if (binder == nullptr || recipient == nullptr) {
- LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
+ LOG(ERROR) << __func__ << ": Must provide binder (" << binder << ") and recipient ("
+ << recipient << ")";
return STATUS_UNEXPECTED_NULL;
}
@@ -625,7 +630,8 @@
binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
if (binder == nullptr || in == nullptr) {
- LOG(ERROR) << __func__ << ": requires non-null parameters.";
+ LOG(ERROR) << __func__ << ": requires non-null parameters binder (" << binder
+ << ") and in (" << in << ").";
return STATUS_UNEXPECTED_NULL;
}
const AIBinder_Class* clazz = binder->getClass();
@@ -671,7 +677,9 @@
AutoParcelDestroyer forIn(in, DestroyParcel);
if (!isUserCommand(code)) {
- LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
+ LOG(ERROR) << __func__
+ << ": Only user-defined transactions can be made from the NDK, but requested: "
+ << code;
return STATUS_UNKNOWN_TRANSACTION;
}
@@ -682,7 +690,8 @@
}
if (binder == nullptr || *in == nullptr || out == nullptr) {
- LOG(ERROR) << __func__ << ": requires non-null parameters.";
+ LOG(ERROR) << __func__ << ": requires non-null parameters binder (" << binder << "), in ("
+ << in << "), and out (" << out << ").";
return STATUS_UNEXPECTED_NULL;
}
diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp
index 2c34766..60b3c94 100644
--- a/libs/binder/tests/binderAllocationLimits.cpp
+++ b/libs/binder/tests/binderAllocationLimits.cpp
@@ -210,8 +210,8 @@
});
CHECK_EQ(OK, remoteBinder->pingBinder());
}
- EXPECT_EQ(mallocs, 2);
- EXPECT_EQ(totalBytes, 56);
+ EXPECT_EQ(mallocs, 1);
+ EXPECT_EQ(totalBytes, 40);
}
int main(int argc, char** argv) {
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 3e90726..4ed3309 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -30,6 +30,7 @@
#include <android-base/properties.h>
#include <android-base/result-gmock.h>
#include <android-base/result.h>
+#include <android-base/scopeguard.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <binder/Binder.h>
@@ -1232,6 +1233,53 @@
EXPECT_THAT(server->transact(BINDER_LIB_TEST_CAN_GET_SID, data, nullptr), StatusEq(OK));
}
+struct TooManyFdsFlattenable : Flattenable<TooManyFdsFlattenable> {
+ TooManyFdsFlattenable(size_t fdCount) : mFdCount(fdCount) {}
+
+ // Flattenable protocol
+ size_t getFlattenedSize() const {
+ // Return a valid non-zero size here so we don't get an unintended
+ // BAD_VALUE from Parcel::write
+ return 16;
+ }
+ size_t getFdCount() const { return mFdCount; }
+ status_t flatten(void *& /*buffer*/, size_t & /*size*/, int *&fds, size_t &count) const {
+ for (size_t i = 0; i < count; i++) {
+ fds[i] = STDIN_FILENO;
+ }
+ return NO_ERROR;
+ }
+ status_t unflatten(void const *& /*buffer*/, size_t & /*size*/, int const *& /*fds*/,
+ size_t & /*count*/) {
+ /* This doesn't get called */
+ return NO_ERROR;
+ }
+
+ size_t mFdCount;
+};
+
+TEST_F(BinderLibTest, TooManyFdsFlattenable) {
+ rlimit origNofile;
+ int ret = getrlimit(RLIMIT_NOFILE, &origNofile);
+ ASSERT_EQ(0, ret);
+
+ // Restore the original file limits when the test finishes
+ base::ScopeGuard guardUnguard([&]() { setrlimit(RLIMIT_NOFILE, &origNofile); });
+
+ rlimit testNofile = {1024, 1024};
+ ret = setrlimit(RLIMIT_NOFILE, &testNofile);
+ ASSERT_EQ(0, ret);
+
+ Parcel parcel;
+ // Try to write more file descriptors than supported by the OS
+ TooManyFdsFlattenable tooManyFds1(1024);
+ EXPECT_THAT(parcel.write(tooManyFds1), StatusEq(-EMFILE));
+
+ // Try to write more file descriptors than the internal limit
+ TooManyFdsFlattenable tooManyFds2(1025);
+ EXPECT_THAT(parcel.write(tooManyFds2), StatusEq(BAD_VALUE));
+}
+
TEST(ServiceNotifications, Unregister) {
auto sm = defaultServiceManager();
using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback;
@@ -1264,7 +1312,9 @@
std::vector<std::thread> ts;
for (size_t i = 0; i < kKernelThreads - 1; i++) {
ts.push_back(std::thread([&] {
- EXPECT_THAT(server->transact(BINDER_LIB_TEST_LOCK_UNLOCK, data, &reply), NO_ERROR);
+ Parcel local_reply;
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_LOCK_UNLOCK, data, &local_reply),
+ NO_ERROR);
}));
}
@@ -1302,7 +1352,9 @@
size_t epochMsBefore = epochMillis();
for (size_t i = 0; i < kKernelThreads + 1; i++) {
ts.push_back(std::thread([&] {
- EXPECT_THAT(server->transact(BINDER_LIB_TEST_LOCK_UNLOCK, data, &reply), NO_ERROR);
+ Parcel local_reply;
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_LOCK_UNLOCK, data, &local_reply),
+ NO_ERROR);
}));
}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 4161a7a..0247e42 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -650,8 +650,11 @@
.proc = createRpcTestSocketServerProcess(
options,
[&](const sp<RpcServer>& server) {
- server->setPerSessionRootObject([&](const sockaddr* addr,
- socklen_t len) {
+ server->setPerSessionRootObject([&](const void* addrPtr, size_t len) {
+ // UNIX sockets with abstract addresses return
+ // sizeof(sa_family_t)==2 in addrlen
+ CHECK_GE(len, sizeof(sa_family_t));
+ const sockaddr* addr = reinterpret_cast<const sockaddr*>(addrPtr);
sp<MyBinderRpcTest> service = sp<MyBinderRpcTest>::make();
switch (addr->sa_family) {
case AF_UNIX:
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
index 0baf1f9..3c7644f 100644
--- a/services/gpuservice/tests/unittests/GpuStatsTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -25,6 +25,7 @@
#include <gtest/gtest.h>
#include <stats_pull_atom_callback.h>
#include <statslog.h>
+#include <utils/Looper.h>
#include <utils/String16.h>
#include <utils/Vector.h>
@@ -62,8 +63,9 @@
// clang-format on
class GpuStatsTest : public testing::Test {
+ sp<android::Looper> looper;
public:
- GpuStatsTest() {
+ GpuStatsTest() : looper(Looper::prepare(0 /* opts */)) {
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
@@ -73,6 +75,10 @@
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+
+ // performs all pending callbacks until all data has been consumed
+ // gives time to process binder transactions by thread pool
+ looper->pollAll(1000);
}
std::string inputCommand(InputCommand cmd);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index a915b61..8680900 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -211,6 +211,7 @@
to_string(getId()).c_str());
return BAD_VALUE;
}
+ mNumModeSwitchesInPolicy++;
mUpcomingActiveMode = info;
ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), info.mode->getFps().getIntValue());
return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), info.mode->getHwcId(),
@@ -537,6 +538,27 @@
mDesiredActiveModeChanged = false;
}
+status_t DisplayDevice::setRefreshRatePolicy(
+ const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy) {
+ const auto oldPolicy = mRefreshRateConfigs->getCurrentPolicy();
+ const status_t setPolicyResult = overridePolicy
+ ? mRefreshRateConfigs->setOverridePolicy(policy)
+ : mRefreshRateConfigs->setDisplayManagerPolicy(*policy);
+
+ if (setPolicyResult == OK) {
+ const int numModeChanges = mNumModeSwitchesInPolicy.exchange(0);
+
+ ALOGI("Display %s policy changed\n"
+ "Previous: {%s}\n"
+ "Current: {%s}\n"
+ "%d mode changes were performed under the previous policy",
+ to_string(getId()).c_str(), oldPolicy.toString().c_str(),
+ policy ? policy->toString().c_str() : "null", numModeChanges);
+ }
+
+ return setPolicyResult;
+}
+
std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1);
} // namespace android
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d5d87b4..2161436 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -249,6 +249,10 @@
nsecs_t getVsyncPeriodFromHWC() const;
nsecs_t getRefreshTimestamp() const;
+ status_t setRefreshRatePolicy(
+ const std::optional<scheduler::RefreshRateConfigs::Policy>& policy,
+ bool overridePolicy);
+
// release HWC resources (if any) for removable displays
void disconnect();
@@ -303,6 +307,8 @@
TracedOrdinal<bool> mDesiredActiveModeChanged
GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false};
ActiveModeInfo mUpcomingActiveMode GUARDED_BY(kMainThreadContext);
+
+ std::atomic_int mNumModeSwitchesInPolicy = 0;
};
struct DisplayDeviceState {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 79320cd..6a290a5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2168,7 +2168,7 @@
if (mLayerTracingEnabled && !mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
// This will block and tracing should only be enabled for debugging.
- mLayerTracing.notify(mVisibleRegionsDirty, frameTime);
+ mLayerTracing.notify(mVisibleRegionsDirty, frameTime, vsyncId);
}
persistDisplayBrightness(mustComposite);
@@ -2295,7 +2295,7 @@
mLayersWithQueuedFrames.clear();
if (mLayerTracingEnabled && mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
// This will block and should only be used for debugging.
- mLayerTracing.notify(mVisibleRegionsDirty, frameTime);
+ mLayerTracing.notify(mVisibleRegionsDirty, frameTime, vsyncId);
}
mVisibleRegionsWereDirtyThisFrame = mVisibleRegionsDirty; // Cache value for use in post-comp
@@ -5850,7 +5850,8 @@
(fixedStartingTime) ? fixedStartingTime : systemTime();
mScheduler
->schedule([&]() FTL_FAKE_GUARD(mStateLock) {
- mLayerTracing.notify("start", startingTime);
+ mLayerTracing.notify(true /* visibleRegionDirty */,
+ startingTime, -1 /* vsyncId */);
})
.wait();
}
@@ -6886,9 +6887,7 @@
return NO_ERROR;
}
- status_t setPolicyResult = overridePolicy
- ? display->refreshRateConfigs().setOverridePolicy(policy)
- : display->refreshRateConfigs().setDisplayManagerPolicy(*policy);
+ const status_t setPolicyResult = display->setRefreshRatePolicy(policy, overridePolicy);
if (setPolicyResult < 0) {
return BAD_VALUE;
}
diff --git a/services/surfaceflinger/Tracing/LayerTracing.cpp b/services/surfaceflinger/Tracing/LayerTracing.cpp
index 49554c7..afa3e50 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.cpp
+++ b/services/surfaceflinger/Tracing/LayerTracing.cpp
@@ -98,7 +98,7 @@
mBuffer->dump(result);
}
-void LayerTracing::notify(bool visibleRegionDirty, int64_t time) {
+void LayerTracing::notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId) {
std::scoped_lock lock(mTraceLock);
if (!mEnabled) {
return;
@@ -129,6 +129,7 @@
entry.set_excludes_composition_state(true);
}
mFlinger.dumpDisplayProto(entry);
+ entry.set_vsync_id(vsyncId);
mBuffer->emplace(std::move(entry));
}
diff --git a/services/surfaceflinger/Tracing/LayerTracing.h b/services/surfaceflinger/Tracing/LayerTracing.h
index 88a19ec..e73dac6 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.h
+++ b/services/surfaceflinger/Tracing/LayerTracing.h
@@ -47,7 +47,7 @@
bool isEnabled() const;
status_t writeToFile();
LayersTraceFileProto createTraceFileProto() const;
- void notify(bool visibleRegionDirty, int64_t time);
+ void notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId);
enum : uint32_t {
TRACE_INPUT = 1 << 1,
diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto
index 13647b6..7def024 100644
--- a/services/surfaceflinger/layerproto/layerstrace.proto
+++ b/services/surfaceflinger/layerproto/layerstrace.proto
@@ -40,7 +40,7 @@
repeated LayersTraceProto entry = 2;
}
-/* one window manager trace entry. */
+/* one layers trace entry. */
message LayersTraceProto {
/* required: elapsed realtime in nanos since boot of when this entry was logged */
optional sfixed64 elapsed_realtime_nanos = 1;
@@ -60,4 +60,6 @@
optional uint32 missed_entries = 6;
repeated DisplayProto displays = 7;
+
+ optional int64 vsync_id = 8;
}