Merge "libbinder*: clarify setDataPosition constraints"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 890c15f..0dab0e4 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -829,7 +829,8 @@
// Logging statement below is useful to time how long each entry takes, but it's too verbose.
// MYLOGD("Adding zip entry %s\n", entry_name.c_str());
- int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
+ size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
+ int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
get_mtime(fd, ds.now_));
if (err != 0) {
MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
@@ -921,7 +922,8 @@
bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
- int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
+ size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
+ int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
if (err != 0) {
MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
ZipWriter::ErrorCodeString(err));
@@ -1648,7 +1650,7 @@
DumpPacketStats();
- RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
+ RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
DoKmsg();
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 3335dc7..ee3a67e 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -3505,10 +3505,10 @@
return error("Failed to stat " + mirrorVolCePath);
}
- if (mirrorCeStat.st_ino == ceStat.st_ino) {
+ if (mirrorCeStat.st_ino == ceStat.st_ino && mirrorCeStat.st_dev == ceStat.st_dev) {
// As it's being called by prepareUserStorage, it can be called multiple times.
// Hence, we if we mount it already, we should skip it.
- LOG(WARNING) << "CE dir is mounted already: " + cePath;
+ LOG(INFO) << "CE dir is mounted already: " + cePath;
return ok();
}
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index bb40f51..3c6769f 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -39,9 +39,16 @@
cc_library_headers {
name: "libarect_headers",
+ vendor_available: true,
+ min_sdk_version: "29",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
export_include_dirs: ["include"],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ "com.android.media.swcodec",
+ ],
}
cc_library_static {
diff --git a/libs/attestation/Android.bp b/libs/attestation/Android.bp
index ea3c341..2bf15d4 100644
--- a/libs/attestation/Android.bp
+++ b/libs/attestation/Android.bp
@@ -28,11 +28,9 @@
"-Werror",
],
srcs: [
- "HmacKeyManager.cpp"
+ "HmacKeyManager.cpp",
],
- clang: true,
-
shared_libs: [
"liblog",
"libcrypto",
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 39befbe..b66e89e 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -539,7 +539,7 @@
return UNEXPECTED_NULL;
}
- size_t binderThreadPoolMaxCount = ProcessState::self()->getThreadPoolMaxThreadCount();
+ size_t binderThreadPoolMaxCount = ProcessState::self()->getThreadPoolMaxTotalThreadCount();
if (binderThreadPoolMaxCount <= 1) {
ALOGE("%s: ProcessState thread pool max count is %zu. RPC is disabled for this service "
"because RPC requires the service to support multithreading.",
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 921e57c..1eb2ffd 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -279,7 +279,7 @@
if (mAlive) {
bool privateVendor = flags & FLAG_PRIVATE_VENDOR;
// don't send userspace flags to the kernel
- flags = flags & ~FLAG_PRIVATE_VENDOR;
+ flags = flags & ~static_cast<uint32_t>(FLAG_PRIVATE_VENDOR);
// user transactions require a given stability level
if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d453ac7..d536219 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -638,7 +638,9 @@
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
-
+ pthread_mutex_lock(&mProcess->mThreadCountLock);
+ mProcess->mCurrentThreads++;
+ pthread_mutex_unlock(&mProcess->mThreadCountLock);
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
mIsLooper = true;
@@ -666,6 +668,13 @@
mOut.writeInt32(BC_EXIT_LOOPER);
mIsLooper = false;
talkWithDriver(false);
+ pthread_mutex_lock(&mProcess->mThreadCountLock);
+ LOG_ALWAYS_FATAL_IF(mProcess->mCurrentThreads == 0,
+ "Threadpool thread count = 0. Thread cannot exist and exit in empty "
+ "threadpool\n"
+ "Misconfiguration. Increase threadpool max threads configuration\n");
+ mProcess->mCurrentThreads--;
+ pthread_mutex_unlock(&mProcess->mThreadCountLock);
}
status_t IPCThreadState::setupPolling(int* fd)
@@ -677,6 +686,9 @@
mOut.writeInt32(BC_ENTER_LOOPER);
flushCommands();
*fd = mProcess->mDriverFD;
+ pthread_mutex_lock(&mProcess->mThreadCountLock);
+ mProcess->mCurrentThreads++;
+ pthread_mutex_unlock(&mProcess->mThreadCountLock);
return 0;
}
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 8132d46..8fe1d2b 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -74,7 +74,7 @@
fd = memfd_create_region(name ? name : "MemoryHeapBase", size);
if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return;
const int SEAL_FLAGS = ((mFlags & READ_ONLY) ? F_SEAL_FUTURE_WRITE : 0) |
- ((mFlags & MEMFD_ALLOW_SEALING) ? 0 : F_SEAL_SEAL);
+ ((mFlags & MEMFD_ALLOW_SEALING_FLAG) ? 0 : F_SEAL_SEAL);
if (SEAL_FLAGS && (fcntl(fd, F_ADD_SEALS, SEAL_FLAGS) == -1)) {
ALOGE("MemoryHeapBase: MemFD %s sealing with flags %x failed with error %s", name,
SEAL_FLAGS, strerror(errno));
@@ -85,12 +85,9 @@
}
return;
#else
- mFlags &= ~(FORCE_MEMFD | MEMFD_ALLOW_SEALING);
+ mFlags &= ~(FORCE_MEMFD | MEMFD_ALLOW_SEALING_FLAG);
#endif
}
- if (mFlags & MEMFD_ALLOW_SEALING) {
- LOG_ALWAYS_FATAL("Invalid Flags. MEMFD_ALLOW_SEALING only valid with FORCE_MEMFD.");
- }
fd = ashmem_create_region(name ? name : "MemoryHeapBase", size);
ALOGE_IF(fd < 0, "MemoryHeapBase: error creating ashmem region: %s", strerror(errno));
if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return;
@@ -103,7 +100,7 @@
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
mDevice(nullptr), mNeedUnmap(false), mOffset(0)
{
- if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) {
+ if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING_FLAG)) {
LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor");
}
int open_flags = O_RDWR;
@@ -125,7 +122,7 @@
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
mDevice(nullptr), mNeedUnmap(false), mOffset(0)
{
- if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) {
+ if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING_FLAG)) {
LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor");
}
const size_t pagesize = getpagesize();
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 68958e6..6beab43 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -175,6 +175,10 @@
// the thread handler is installed
if (gProcess) {
gProcess->mForked = true;
+
+ // "O_CLOFORK"
+ close(gProcess->mDriverFD);
+ gProcess->mDriverFD = -1;
}
gProcessMutex.unlock();
}
@@ -187,7 +191,6 @@
ALOGW("Extra binder thread started, but 0 threads requested. Do not use "
"*startThreadPool when zero threads are requested.");
}
-
mThreadPoolStarted = true;
spawnPooledThread(true);
}
@@ -295,12 +298,17 @@
return &mHandleToObject.editItemAt(handle);
}
+// see b/166779391: cannot change the VNDK interface, so access like this
+extern sp<BBinder> the_context_object;
+
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
+ if (handle == 0 && the_context_object != nullptr) return the_context_object;
+
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
@@ -391,6 +399,7 @@
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = sp<PoolThread>::make(isMain);
t->run(name.string());
+ mKernelStartedThreads++;
}
}
@@ -407,12 +416,20 @@
return result;
}
-size_t ProcessState::getThreadPoolMaxThreadCount() const {
+size_t ProcessState::getThreadPoolMaxTotalThreadCount() const {
// may actually be one more than this, if join is called
- if (mThreadPoolStarted) return mMaxThreads;
+ if (mThreadPoolStarted) {
+ return mCurrentThreads < mKernelStartedThreads
+ ? mMaxThreads
+ : mMaxThreads + mCurrentThreads - mKernelStartedThreads;
+ }
// must not be initialized or maybe has poll thread setup, we
// currently don't track this in libbinder
- return 0;
+ LOG_ALWAYS_FATAL_IF(mKernelStartedThreads != 0,
+ "Expecting 0 kernel started threads but have"
+ " %zu",
+ mKernelStartedThreads);
+ return mCurrentThreads;
}
#define DRIVER_FEATURES_PATH "/dev/binderfs/features/"
@@ -498,6 +515,8 @@
mExecutingThreadsCount(0),
mWaitingForThreads(0),
mMaxThreads(DEFAULT_MAX_BINDER_THREADS),
+ mCurrentThreads(0),
+ mKernelStartedThreads(0),
mStarvationStartTimeMs(0),
mForked(false),
mThreadPoolStarted(false),
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index ace5cd5..d63c3f1 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -24,18 +24,19 @@
#include <thread>
#include <vector>
-#include <android-base/file.h>
#include <android-base/hex.h>
#include <android-base/scopeguard.h>
#include <binder/Parcel.h>
#include <binder/RpcServer.h>
#include <binder/RpcTransportRaw.h>
#include <log/log.h>
+#include <utils/Compat.h>
#include "FdTrigger.h"
#include "RpcSocketAddress.h"
#include "RpcState.h"
#include "RpcWireFormat.h"
+#include "Utils.h"
namespace android {
@@ -380,10 +381,9 @@
return;
}
- base::unique_fd fd(TEMP_FAILURE_RETRY(
- open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW)));
- if (!base::ReadFully(fd, sessionId.data(), sessionId.size())) {
- ALOGE("Could not read from /dev/urandom to create session ID");
+ auto status = getRandomBytes(sessionId.data(), sessionId.size());
+ if (status != OK) {
+ ALOGE("Failed to read random session ID: %s", strerror(-status));
return;
}
} while (server->mSessions.end() != server->mSessions.find(sessionId));
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 16991db..6ae5357 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -34,6 +34,7 @@
#include <binder/RpcServer.h>
#include <binder/RpcTransportRaw.h>
#include <binder/Stability.h>
+#include <utils/Compat.h>
#include <utils/String8.h>
#include "FdTrigger.h"
@@ -42,11 +43,7 @@
#include "RpcWireFormat.h"
#include "Utils.h"
-#ifdef __GLIBC__
-extern "C" pid_t gettid();
-#endif
-
-#ifndef __ANDROID_RECOVERY__
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
#include <android_runtime/vm.h>
#include <jni.h>
#endif
@@ -319,7 +316,7 @@
}
namespace {
-#ifdef __ANDROID_RECOVERY__
+#if !defined(__ANDROID__) || defined(__ANDROID_RECOVERY__)
class JavaThreadAttacher {};
#else
// RAII object for attaching / detaching current thread to JVM if Android Runtime exists. If
@@ -692,7 +689,7 @@
{
std::lock_guard<std::mutex> _l(mMutex);
connection->rpcTransport = std::move(rpcTransport);
- connection->exclusiveTid = gettid();
+ connection->exclusiveTid = base::GetThreadId();
mConnections.mOutgoing.push_back(connection);
}
@@ -749,7 +746,7 @@
sp<RpcConnection> session = sp<RpcConnection>::make();
session->rpcTransport = std::move(rpcTransport);
- session->exclusiveTid = gettid();
+ session->exclusiveTid = base::GetThreadId();
mConnections.mIncoming.push_back(session);
mConnections.mMaxIncoming = mConnections.mIncoming.size();
@@ -785,7 +782,7 @@
connection->mConnection = nullptr;
connection->mReentrant = false;
- pid_t tid = gettid();
+ uint64_t tid = base::GetThreadId();
std::unique_lock<std::mutex> _l(session->mMutex);
session->mConnections.mWaitingThreads++;
@@ -872,7 +869,7 @@
return OK;
}
-void RpcSession::ExclusiveConnection::findConnection(pid_t tid, sp<RpcConnection>* exclusive,
+void RpcSession::ExclusiveConnection::findConnection(uint64_t tid, sp<RpcConnection>* exclusive,
sp<RpcConnection>* available,
std::vector<sp<RpcConnection>>& sockets,
size_t socketsIndexHint) {
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 6d89064..4ef9cd8 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -661,13 +661,10 @@
status_t RpcState::drainCommands(const sp<RpcSession::RpcConnection>& connection,
const sp<RpcSession>& session, CommandType type) {
- uint8_t buf;
while (true) {
- size_t num_bytes;
- status_t status = connection->rpcTransport->peek(&buf, sizeof(buf), &num_bytes);
+ status_t status = connection->rpcTransport->pollRead();
if (status == WOULD_BLOCK) break;
if (status != OK) return status;
- if (!num_bytes) break;
status = getAndExecuteCommand(connection, session, type);
if (status != OK) return status;
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 7cfc780..f5cc413 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -32,19 +32,22 @@
class RpcTransportRaw : public RpcTransport {
public:
explicit RpcTransportRaw(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
- status_t peek(void* buf, size_t size, size_t* out_size) override {
- ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK));
+ status_t pollRead(void) override {
+ uint8_t buf;
+ ssize_t ret = TEMP_FAILURE_RETRY(
+ ::recv(mSocket.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT));
if (ret < 0) {
int savedErrno = errno;
if (savedErrno == EAGAIN || savedErrno == EWOULDBLOCK) {
return WOULD_BLOCK;
}
- LOG_RPC_DETAIL("RpcTransport peek(): %s", strerror(savedErrno));
+ LOG_RPC_DETAIL("RpcTransport poll(): %s", strerror(savedErrno));
return -savedErrno;
+ } else if (ret == 0) {
+ return DEAD_OBJECT;
}
- *out_size = static_cast<size_t>(ret);
return OK;
}
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
index bc68c37..85c7655 100644
--- a/libs/binder/RpcTransportTls.cpp
+++ b/libs/binder/RpcTransportTls.cpp
@@ -277,7 +277,7 @@
public:
RpcTransportTls(android::base::unique_fd socket, Ssl ssl)
: mSocket(std::move(socket)), mSsl(std::move(ssl)) {}
- status_t peek(void* buf, size_t size, size_t* out_size) override;
+ status_t pollRead(void) override;
status_t interruptableWriteFully(FdTrigger* fdTrigger, iovec* iovs, int niovs,
const std::function<status_t()>& altPoll) override;
status_t interruptableReadFully(FdTrigger* fdTrigger, iovec* iovs, int niovs,
@@ -289,9 +289,9 @@
};
// Error code is errno.
-status_t RpcTransportTls::peek(void* buf, size_t size, size_t* out_size) {
- size_t todo = std::min<size_t>(size, std::numeric_limits<int>::max());
- auto [ret, errorQueue] = mSsl.call(SSL_peek, buf, static_cast<int>(todo));
+status_t RpcTransportTls::pollRead(void) {
+ uint8_t buf;
+ auto [ret, errorQueue] = mSsl.call(SSL_peek, &buf, sizeof(buf));
if (ret < 0) {
int err = mSsl.getError(ret);
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
@@ -304,7 +304,6 @@
}
errorQueue.clear();
LOG_TLS_DETAIL("TLS: Peeked %d bytes!", ret);
- *out_size = static_cast<size_t>(ret);
return OK;
}
diff --git a/libs/binder/Utils.cpp b/libs/binder/Utils.cpp
index d2a5be1..b0289a7 100644
--- a/libs/binder/Utils.cpp
+++ b/libs/binder/Utils.cpp
@@ -16,6 +16,7 @@
#include "Utils.h"
+#include <android-base/file.h>
#include <string.h>
using android::base::ErrnoError;
@@ -38,4 +39,17 @@
return {};
}
+status_t getRandomBytes(uint8_t* data, size_t size) {
+ int ret = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+ if (ret == -1) {
+ return -errno;
+ }
+
+ base::unique_fd fd(ret);
+ if (!base::ReadFully(fd, data, size)) {
+ return -errno;
+ }
+ return OK;
+}
+
} // namespace android
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
index ff2fad8..150d520 100644
--- a/libs/binder/Utils.h
+++ b/libs/binder/Utils.h
@@ -20,6 +20,7 @@
#include <android-base/result.h>
#include <android-base/unique_fd.h>
#include <log/log.h>
+#include <utils/Errors.h>
#define TEST_AND_RETURN(value, expr) \
do { \
@@ -36,4 +37,6 @@
android::base::Result<void> setNonBlocking(android::base::borrowed_fd fd);
+status_t getRandomBytes(uint8_t* data, size_t size);
+
} // namespace android
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index 15dd28f..c7177bd 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -26,9 +26,10 @@
// ---------------------------------------------------------------------------
-class MemoryHeapBase : public virtual BnMemoryHeap
+class MemoryHeapBase : public BnMemoryHeap
{
public:
+ static constexpr auto MEMFD_ALLOW_SEALING_FLAG = 0x00000800;
enum {
READ_ONLY = IMemoryHeap::READ_ONLY,
// memory won't be mapped locally, but will be mapped in the remote
@@ -48,7 +49,7 @@
// Clients of shared files can seal at anytime via syscall, leading to
// TOC/TOU issues if additional seals prevent access from the creating
// process. Alternatively, seccomp fcntl().
- MEMFD_ALLOW_SEALING = 0x00000800
+ MEMFD_ALLOW_SEALING = FORCE_MEMFD | MEMFD_ALLOW_SEALING_FLAG
};
/*
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 5820802..e17a76c 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -84,11 +84,11 @@
void setCallRestriction(CallRestriction restriction);
/**
- * Get the max number of threads that the kernel can start.
- *
- * Note: this is the lower bound. Additional threads may be started.
+ * Get the max number of threads that have joined the thread pool.
+ * This includes kernel started threads, user joined threads and polling
+ * threads if used.
*/
- size_t getThreadPoolMaxThreadCount() const;
+ size_t getThreadPoolMaxTotalThreadCount() const;
enum class DriverFeature {
ONEWAY_SPAM_DETECTION,
@@ -133,8 +133,12 @@
size_t mExecutingThreadsCount;
// Number of threads calling IPCThreadState::blockUntilThreadAvailable()
size_t mWaitingForThreads;
- // Maximum number for binder threads allowed for this process.
+ // Maximum number of lazy threads to be started in the threadpool by the kernel.
size_t mMaxThreads;
+ // Current number of threads inside the thread pool.
+ size_t mCurrentThreads;
+ // Current number of pooled threads inside the thread pool.
+ size_t mKernelStartedThreads;
// Time when thread pool was emptied
int64_t mStarvationStartTimeMs;
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index a579442..cb81584 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <android-base/threads.h>
#include <android-base/unique_fd.h>
#include <binder/IBinder.h>
#include <binder/RpcTransport.h>
@@ -211,7 +212,7 @@
// whether this or another thread is currently using this fd to make
// or receive transactions.
- std::optional<pid_t> exclusiveTid;
+ std::optional<uint64_t> exclusiveTid;
bool allowNested = false;
};
@@ -276,7 +277,7 @@
const sp<RpcConnection>& get() { return mConnection; }
private:
- static void findConnection(pid_t tid, sp<RpcConnection>* exclusive,
+ static void findConnection(uint64_t tid, sp<RpcConnection>* exclusive,
sp<RpcConnection>* available,
std::vector<sp<RpcConnection>>& sockets,
size_t socketsIndexHint);
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index 751c4f9..2c864f8 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -39,8 +39,15 @@
public:
virtual ~RpcTransport() = default;
- // replacement of ::recv(MSG_PEEK). Error code may not be set if TLS is enabled.
- [[nodiscard]] virtual status_t peek(void *buf, size_t size, size_t *out_size) = 0;
+ /**
+ * Poll the transport to check whether there is any data ready to read.
+ *
+ * Return:
+ * OK - There is data available on this transport
+ * WOULDBLOCK - No data is available
+ * error - any other error
+ */
+ [[nodiscard]] virtual status_t pollRead(void) = 0;
/**
* Read (or write), but allow to be interrupted by a trigger.
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 57a1fda..18a9f86 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -82,6 +82,7 @@
static constexpr int kSchedPolicy = SCHED_RR;
static constexpr int kSchedPriority = 7;
static constexpr int kSchedPriorityMore = 8;
+static constexpr int kKernelThreads = 15;
static String16 binderLibTestServiceName = String16("test.binderLib");
@@ -115,6 +116,12 @@
BINDER_LIB_TEST_ECHO_VECTOR,
BINDER_LIB_TEST_REJECT_OBJECTS,
BINDER_LIB_TEST_CAN_GET_SID,
+ BINDER_LIB_TEST_GET_MAX_THREAD_COUNT,
+ BINDER_LIB_TEST_SET_MAX_THREAD_COUNT,
+ BINDER_LIB_TEST_LOCK_UNLOCK,
+ BINDER_LIB_TEST_PROCESS_LOCK,
+ BINDER_LIB_TEST_UNLOCK_AFTER_MS,
+ BINDER_LIB_TEST_PROCESS_TEMPORARY_LOCK
};
pid_t start_server_process(int arg2, bool usePoll = false)
@@ -440,6 +447,12 @@
EXPECT_DEATH({ ProcessState::self(); }, "libbinder ProcessState can not be used after fork");
}
+TEST_F(BinderLibTest, AddManagerToManager) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = IInterface::asBinder(sm);
+ EXPECT_EQ(NO_ERROR, sm->addService(String16("binderLibTest-manager"), binder));
+}
+
TEST_F(BinderLibTest, WasParceled) {
auto binder = sp<BBinder>::make();
EXPECT_FALSE(binder->wasParceled());
@@ -1232,6 +1245,76 @@
EXPECT_EQ(sm->unregisterForNotifications(String16("RogerRafa"), cb), OK);
}
+TEST_F(BinderLibTest, ThreadPoolAvailableThreads) {
+ Parcel data, reply;
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_MAX_THREAD_COUNT, data, &reply),
+ StatusEq(NO_ERROR));
+ int32_t replyi = reply.readInt32();
+ // Expect 16 threads: kKernelThreads = 15 + Pool thread == 16
+ EXPECT_TRUE(replyi == kKernelThreads || replyi == kKernelThreads + 1);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_PROCESS_LOCK, data, &reply), NO_ERROR);
+
+ /*
+ * This will use all threads in the pool expect the main pool thread.
+ * The service should run fine without locking, and the thread count should
+ * not exceed 16 (15 Max + pool thread).
+ */
+ 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);
+ }));
+ }
+
+ data.writeInt32(1);
+ // Give a chance for all threads to be used
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_UNLOCK_AFTER_MS, data, &reply), NO_ERROR);
+
+ for (auto &t : ts) {
+ t.join();
+ }
+
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_MAX_THREAD_COUNT, data, &reply),
+ StatusEq(NO_ERROR));
+ replyi = reply.readInt32();
+ // No more than 16 threads should exist.
+ EXPECT_EQ(replyi, kKernelThreads + 1);
+}
+
+size_t epochMillis() {
+ using std::chrono::duration_cast;
+ using std::chrono::milliseconds;
+ using std::chrono::seconds;
+ using std::chrono::system_clock;
+ return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+}
+
+TEST_F(BinderLibTest, HangingServices) {
+ Parcel data, reply;
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+ int32_t delay = 1000; // ms
+ data.writeInt32(delay);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_PROCESS_TEMPORARY_LOCK, data, &reply), NO_ERROR);
+ std::vector<std::thread> ts;
+ 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);
+ }));
+ }
+
+ for (auto &t : ts) {
+ t.join();
+ }
+ size_t epochMsAfter = epochMillis();
+
+ // deadlock occurred and threads only finished after 1s passed.
+ EXPECT_GE(epochMsAfter, epochMsBefore + delay);
+}
+
class BinderLibRpcTestBase : public BinderLibTest {
public:
void SetUp() override {
@@ -1638,11 +1721,41 @@
case BINDER_LIB_TEST_CAN_GET_SID: {
return IPCThreadState::self()->getCallingSid() == nullptr ? BAD_VALUE : NO_ERROR;
}
+ case BINDER_LIB_TEST_GET_MAX_THREAD_COUNT: {
+ reply->writeInt32(ProcessState::self()->getThreadPoolMaxTotalThreadCount());
+ return NO_ERROR;
+ }
+ case BINDER_LIB_TEST_PROCESS_LOCK: {
+ blockMutex.lock();
+ return NO_ERROR;
+ }
+ case BINDER_LIB_TEST_LOCK_UNLOCK: {
+ std::lock_guard<std::mutex> _l(blockMutex);
+ return NO_ERROR;
+ }
+ case BINDER_LIB_TEST_UNLOCK_AFTER_MS: {
+ int32_t ms = data.readInt32();
+ return unlockInMs(ms);
+ }
+ case BINDER_LIB_TEST_PROCESS_TEMPORARY_LOCK: {
+ blockMutex.lock();
+ std::thread t([&] {
+ unlockInMs(data.readInt32());
+ }); // start local thread to unlock in 1s
+ t.detach();
+ return NO_ERROR;
+ }
default:
return UNKNOWN_TRANSACTION;
};
}
+ status_t unlockInMs(int32_t ms) {
+ usleep(ms * 1000);
+ blockMutex.unlock();
+ return NO_ERROR;
+ }
+
private:
int32_t m_id;
int32_t m_nextServerId;
@@ -1653,6 +1766,7 @@
sp<IBinder> m_strongRef;
sp<IBinder> m_callback;
bool m_exitOnDestroy;
+ std::mutex blockMutex;
};
int run_server(int index, int readypipefd, bool usePoll)
@@ -1754,6 +1868,7 @@
}
}
} else {
+ ProcessState::self()->setThreadPoolMaxThreadCount(kKernelThreads);
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
diff --git a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp
index 21cb70b..278dd2b 100644
--- a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp
+++ b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp
@@ -23,6 +23,7 @@
#ifdef __BIONIC__
TEST(MemoryHeapBase, ForceMemfdRespected) {
auto mHeap = sp<MemoryHeapBase>::make(10, MemoryHeapBase::FORCE_MEMFD, "Test mapping");
+ ASSERT_NE(mHeap.get(), nullptr);
int fd = mHeap->getHeapID();
EXPECT_NE(fd, -1);
EXPECT_FALSE(ashmem_valid(fd));
@@ -33,6 +34,7 @@
auto mHeap = sp<MemoryHeapBase>::make(8192,
MemoryHeapBase::FORCE_MEMFD,
"Test mapping");
+ ASSERT_NE(mHeap.get(), nullptr);
int fd = mHeap->getHeapID();
EXPECT_NE(fd, -1);
EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL);
@@ -43,6 +45,7 @@
MemoryHeapBase::FORCE_MEMFD |
MemoryHeapBase::MEMFD_ALLOW_SEALING,
"Test mapping");
+ ASSERT_NE(mHeap.get(), nullptr);
int fd = mHeap->getHeapID();
EXPECT_NE(fd, -1);
EXPECT_EQ(fcntl(fd, F_GET_SEALS), 0);
@@ -53,6 +56,7 @@
MemoryHeapBase::FORCE_MEMFD |
MemoryHeapBase::READ_ONLY,
"Test mapping");
+ ASSERT_NE(mHeap.get(), nullptr);
int fd = mHeap->getHeapID();
EXPECT_NE(fd, -1);
EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL | F_SEAL_FUTURE_WRITE);
@@ -64,6 +68,7 @@
MemoryHeapBase::READ_ONLY |
MemoryHeapBase::MEMFD_ALLOW_SEALING,
"Test mapping");
+ ASSERT_NE(mHeap.get(), nullptr);
int fd = mHeap->getHeapID();
EXPECT_NE(fd, -1);
EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_FUTURE_WRITE);
@@ -74,6 +79,7 @@
auto mHeap = sp<MemoryHeapBase>::make(8192,
MemoryHeapBase::READ_ONLY,
"Test mapping");
+ ASSERT_NE(mHeap.get(), nullptr);
int fd = mHeap->getHeapID();
void* ptr = mHeap->getBase();
EXPECT_NE(ptr, MAP_FAILED);
@@ -87,6 +93,7 @@
MemoryHeapBase::READ_ONLY |
MemoryHeapBase::MEMFD_ALLOW_SEALING,
"Test mapping");
+ ASSERT_NE(mHeap.get(), nullptr);
int fd = mHeap->getHeapID();
void* ptr = mHeap->getBase();
EXPECT_EQ(mHeap->getFlags(), MemoryHeapBase::READ_ONLY);
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 47ec776..7059d30 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -73,20 +73,20 @@
uint8_t data[1337];
};
-#define PARCEL_READ_WITH_STATUS(T, FUN) \
- [] (const ::android::Parcel& p, uint8_t /*data*/) {\
- FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\
- T t{};\
- status_t status = p.FUN(&t);\
- FUZZ_LOG() << #T " status: " << status /* << " value: " << t*/;\
+#define PARCEL_READ_WITH_STATUS(T, FUN) \
+ [](const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { \
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \
+ T t{}; \
+ status_t status = p.FUN(&t); \
+ FUZZ_LOG() << #T " status: " << status /* << " value: " << t*/; \
}
-#define PARCEL_READ_NO_STATUS(T, FUN) \
- [] (const ::android::Parcel& p, uint8_t /*data*/) {\
- FUZZ_LOG() << "about to read " #T " using " #FUN " with no status";\
- T t = p.FUN();\
- (void) t;\
- FUZZ_LOG() << #T " done " /* << " value: " << t*/;\
+#define PARCEL_READ_NO_STATUS(T, FUN) \
+ [](const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { \
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with no status"; \
+ T t = p.FUN(); \
+ (void)t; \
+ FUZZ_LOG() << #T " done " /* << " value: " << t*/; \
}
#define PARCEL_READ_OPT_STATUS(T, FUN) \
@@ -102,7 +102,9 @@
PARCEL_READ_NO_STATUS(size_t, dataPosition),
PARCEL_READ_NO_STATUS(size_t, dataCapacity),
PARCEL_READ_NO_STATUS(::android::binder::Status, enforceNoDataAvail),
- [] (const ::android::Parcel& p, uint8_t pos) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& provider) {
+ // aborts on larger values
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, INT32_MAX);
FUZZ_LOG() << "about to setDataPosition: " << pos;
p.setDataPosition(pos);
FUZZ_LOG() << "setDataPosition done";
@@ -111,13 +113,13 @@
PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors),
PARCEL_READ_NO_STATUS(std::vector<android::sp<android::IBinder>>, debugReadAllStrongBinders),
PARCEL_READ_NO_STATUS(std::vector<int>, debugReadAllFileDescriptors),
- [] (const ::android::Parcel& p, uint8_t len) {
- std::string interface(len, 'a');
+ [] (const ::android::Parcel& p, FuzzedDataProvider& provider) {
+ std::string interface = provider.ConsumeRandomLengthString();
FUZZ_LOG() << "about to enforceInterface: " << interface;
bool b = p.enforceInterface(::android::String16(interface.c_str()));
FUZZ_LOG() << "enforced interface: " << b;
},
- [] (const ::android::Parcel& p, uint8_t /*len*/) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to checkInterface";
android::sp<android::IBinder> aBinder = new android::BBinder();
bool b = p.checkInterface(aBinder.get());
@@ -125,13 +127,16 @@
},
PARCEL_READ_NO_STATUS(size_t, objectsCount),
PARCEL_READ_NO_STATUS(status_t, errorCheck),
- [] (const ::android::Parcel& p, uint8_t len) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& provider) {
+ // Read at least a bit. Unbounded allocation would OOM.
+ size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024);
FUZZ_LOG() << "about to read void*";
std::vector<uint8_t> data(len);
status_t status = p.read(data.data(), len);
FUZZ_LOG() << "read status: " << status;
},
- [] (const ::android::Parcel& p, uint8_t len) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& provider) {
+ size_t len = provider.ConsumeIntegral<size_t>();
FUZZ_LOG() << "about to readInplace";
const void* r = p.readInplace(len);
FUZZ_LOG() << "readInplace done. pointer: " << r << " bytes: " << (r ? HexString(r, len) : "null");
@@ -149,13 +154,13 @@
PARCEL_READ_WITH_STATUS(std::string, readUtf8FromUtf16),
PARCEL_READ_WITH_STATUS(std::unique_ptr<std::string>, readUtf8FromUtf16),
PARCEL_READ_WITH_STATUS(std::optional<std::string>, readUtf8FromUtf16),
- [] (const ::android::Parcel& p, uint8_t /*data*/) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to read c-str";
const char* str = p.readCString();
FUZZ_LOG() << "read c-str: " << (str ? str : "<empty string>");
},
PARCEL_READ_OPT_STATUS(android::String8, readString8),
- [] (const ::android::Parcel& p, uint8_t /*data*/) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to readString8Inplace";
size_t outLen = 0;
const char* str = p.readString8Inplace(&outLen);
@@ -165,7 +170,7 @@
PARCEL_READ_OPT_STATUS(android::String16, readString16),
PARCEL_READ_WITH_STATUS(std::unique_ptr<android::String16>, readString16),
PARCEL_READ_WITH_STATUS(std::optional<android::String16>, readString16),
- [] (const ::android::Parcel& p, uint8_t /*data*/) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to readString16Inplace";
size_t outLen = 0;
const char16_t* str = p.readString16Inplace(&outLen);
@@ -263,13 +268,13 @@
PARCEL_READ_WITH_STATUS(std::optional<std::array<std::array<std::optional<ExampleParcelable> COMMA 3> COMMA 4>>, readFixedArray),
#undef COMMA
- [] (const android::Parcel& p, uint8_t /*len*/) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to read flattenable";
ExampleFlattenable f;
status_t status = p.read(f);
FUZZ_LOG() << "read flattenable: " << status;
},
- [] (const android::Parcel& p, uint8_t /*len*/) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to read lite flattenable";
ExampleLightFlattenable f;
status_t status = p.read(f);
@@ -284,7 +289,7 @@
PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<BigStruct>>, resizeOutVector),
PARCEL_READ_NO_STATUS(int32_t, readExceptionCode),
- [] (const android::Parcel& p, uint8_t /*len*/) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to readNativeHandle";
native_handle_t* t = p.readNativeHandle();
FUZZ_LOG() << "readNativeHandle: " << t;
@@ -303,15 +308,16 @@
PARCEL_READ_WITH_STATUS(std::optional<std::vector<android::base::unique_fd>>, readUniqueFileDescriptorVector),
PARCEL_READ_WITH_STATUS(std::vector<android::base::unique_fd>, readUniqueFileDescriptorVector),
- [] (const android::Parcel& p, uint8_t len) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& provider) {
+ size_t len = provider.ConsumeIntegral<size_t>();
FUZZ_LOG() << "about to readBlob";
::android::Parcel::ReadableBlob blob;
status_t status = p.readBlob(len, &blob);
FUZZ_LOG() << "readBlob status: " << status;
},
- [] (const android::Parcel& p, uint8_t options) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& provider) {
FUZZ_LOG() << "about to readObject";
- bool nullMetaData = options & 0x1;
+ bool nullMetaData = provider.ConsumeBool();
const void* obj = static_cast<const void*>(p.readObject(nullMetaData));
FUZZ_LOG() << "readObject: " << obj;
},
@@ -319,20 +325,19 @@
PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize),
// additional parcelable objects defined in libbinder
- [] (const ::android::Parcel& p, uint8_t data) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& provider) {
using ::android::os::ParcelableHolder;
using ::android::Parcelable;
FUZZ_LOG() << "about to read ParcelableHolder using readParcelable with status";
- Parcelable::Stability stability = Parcelable::Stability::STABILITY_LOCAL;
- if ( (data & 1) == 1 ) {
- stability = Parcelable::Stability::STABILITY_VINTF;
- }
+ Parcelable::Stability stability = provider.ConsumeBool()
+ ? Parcelable::Stability::STABILITY_LOCAL
+ : Parcelable::Stability::STABILITY_VINTF;
ParcelableHolder t = ParcelableHolder(stability);
status_t status = p.readParcelable(&t);
FUZZ_LOG() << "ParcelableHolder status: " << status;
},
PARCEL_READ_WITH_STATUS(android::os::PersistableBundle, readParcelable),
- [] (const ::android::Parcel& p, uint8_t /* data */) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to call hasFileDescriptorsInRange() with status";
size_t offset = p.readUint32();
size_t length = p.readUint32();
@@ -340,7 +345,7 @@
status_t status = p.hasFileDescriptorsInRange(offset, length, &result);
FUZZ_LOG() << " status: " << status << " result: " << result;
},
- [] (const ::android::Parcel& p, uint8_t /* data */) {
+ [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to call compareDataInRange() with status";
size_t thisOffset = p.readUint32();
size_t otherOffset = p.readUint32();
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 5aeb5cc..26d6770 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -70,7 +70,7 @@
}
#define PARCEL_READ(T, FUN) \
- [](const NdkParcelAdapter& p, uint8_t /*data*/) { \
+ [](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) { \
FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \
T t{}; \
binder_status_t status = FUN(p.aParcel(), &t); \
@@ -80,32 +80,37 @@
// clang-format off
std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{
// methods from binder_parcel.h
- [](const NdkParcelAdapter& p, uint8_t pos) {
+ [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) {
+ // aborts on larger values
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, INT32_MAX);
FUZZ_LOG() << "about to set data position to " << pos;
binder_status_t status = AParcel_setDataPosition(p.aParcel(), pos);
FUZZ_LOG() << "set data position: " << status;
},
- [](const NdkParcelAdapter& p, uint8_t /*data*/) {
+ [](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to read status header";
ndk::ScopedAStatus t;
binder_status_t status = AParcel_readStatusHeader(p.aParcel(), t.getR());
FUZZ_LOG() << "read status header: " << status;
},
- [](const NdkParcelAdapter& p, uint8_t /*data*/) {
+ [](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to getDataSize the parcel";
AParcel_getDataSize(p.aParcel());
FUZZ_LOG() << "getDataSize done";
},
- [](const NdkParcelAdapter& p, uint8_t data) {
+ [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) {
FUZZ_LOG() << "about to read a ParcelableHolder";
- ndk::AParcelableHolder ph {(data % 2 == 1) ? ndk::STABILITY_LOCAL : ndk::STABILITY_VINTF};
+ ndk::AParcelableHolder ph {provider.ConsumeBool() ? ndk::STABILITY_LOCAL : ndk::STABILITY_VINTF};
binder_status_t status = AParcel_readParcelable(p.aParcel(), &ph);
FUZZ_LOG() << "read the ParcelableHolder: " << status;
},
- [](const NdkParcelAdapter& p, uint8_t data) {
- FUZZ_LOG() << "about to appendFrom";
+ [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) {
+ size_t offset = provider.ConsumeIntegral<size_t>();
+ size_t pos = provider.ConsumeIntegral<size_t>();
+ FUZZ_LOG() << "about to appendFrom " << pos;
+ // TODO: create random parcel
AParcel* parcel = AParcel_create();
- binder_status_t status = AParcel_appendFrom(p.aParcel(), parcel, 0, data);
+ binder_status_t status = AParcel_appendFrom(p.aParcel(), parcel, offset, pos);
AParcel_delete(parcel);
FUZZ_LOG() << "appendFrom: " << status;
},
diff --git a/libs/binder/tests/parcel_fuzzer/hwbinder.cpp b/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
index ee9840f..438e8ae 100644
--- a/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
@@ -35,19 +35,19 @@
#define PARCEL_READ_OPT_STATUS(T, FUN) \
PARCEL_READ_NO_STATUS(T, FUN), PARCEL_READ_WITH_STATUS(T, FUN)
-#define PARCEL_READ_NO_STATUS(T, FUN) \
- [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\
- FUZZ_LOG() << "about to read " #T " using " #FUN " with no status";\
- T t = p.FUN();\
- FUZZ_LOG() << #T " value: " << t;\
+#define PARCEL_READ_NO_STATUS(T, FUN) \
+ [](const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { \
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with no status"; \
+ T t = p.FUN(); \
+ FUZZ_LOG() << #T " value: " << t; \
}
-#define PARCEL_READ_WITH_STATUS(T, FUN) \
- [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\
- FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\
- T t;\
- status_t status = p.FUN(&t);\
- FUZZ_LOG() << #T " status: " << status << " value: " << t;\
+#define PARCEL_READ_WITH_STATUS(T, FUN) \
+ [](const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { \
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \
+ T t; \
+ status_t status = p.FUN(&t); \
+ FUZZ_LOG() << #T " status: " << status << " value: " << t; \
}
// clang-format off
@@ -56,27 +56,30 @@
PARCEL_READ_NO_STATUS(size_t, dataAvail),
PARCEL_READ_NO_STATUS(size_t, dataPosition),
PARCEL_READ_NO_STATUS(size_t, dataCapacity),
- [] (const ::android::hardware::Parcel& p, uint8_t pos) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) {
+ // aborts on larger values
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, INT32_MAX);
FUZZ_LOG() << "about to setDataPosition: " << pos;
p.setDataPosition(pos);
FUZZ_LOG() << "setDataPosition done";
},
- [] (const ::android::hardware::Parcel& p, uint8_t length) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) {
FUZZ_LOG() << "about to enforceInterface";
- std::string interfaceName(length, 'a');
- bool okay = p.enforceInterface(interfaceName.c_str());
+ bool okay = p.enforceInterface(provider.ConsumeRandomLengthString().c_str());
FUZZ_LOG() << "enforceInterface status: " << okay;
},
PARCEL_READ_NO_STATUS(size_t, objectsCount),
- [] (const ::android::hardware::Parcel& p, uint8_t length) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) {
+ // Read at least a bit. Unbounded allocation would OOM.
+ size_t length = provider.ConsumeIntegralInRange<size_t>(0, 1024);
FUZZ_LOG() << "about to read";
std::vector<uint8_t> data (length);
status_t status = p.read(data.data(), length);
FUZZ_LOG() << "read status: " << status << " data: " << HexString(data.data(), data.size());
},
- [] (const ::android::hardware::Parcel& p, uint8_t length) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) {
+ size_t length = provider.ConsumeIntegral<size_t>();
FUZZ_LOG() << "about to read";
- std::vector<uint8_t> data (length);
const void* inplace = p.readInplace(length);
FUZZ_LOG() << "read status: " << (inplace ? HexString(inplace, length) : "null");
},
@@ -91,14 +94,14 @@
PARCEL_READ_OPT_STATUS(float, readFloat),
PARCEL_READ_OPT_STATUS(double, readDouble),
PARCEL_READ_OPT_STATUS(bool, readBool),
- [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to readCString";
const char* str = p.readCString();
FUZZ_LOG() << "readCString " << (str ? str : "<null>");
},
PARCEL_READ_OPT_STATUS(::android::String16, readString16),
PARCEL_READ_WITH_STATUS(std::unique_ptr<::android::String16>, readString16),
- [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to readString16Inplace";
size_t outSize = 0;
const char16_t* str = p.readString16Inplace(&outSize);
@@ -106,7 +109,8 @@
},
PARCEL_READ_OPT_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder),
PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder),
- [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) {
+ size_t size = provider.ConsumeIntegral<size_t>();
FUZZ_LOG() << "about to readBuffer";
size_t handle = 0;
const void* data = nullptr;
@@ -116,7 +120,8 @@
// should be null since we don't create any IPC objects
CHECK(data == nullptr) << data;
},
- [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) {
+ size_t size = provider.ConsumeIntegral<size_t>();
FUZZ_LOG() << "about to readNullableBuffer";
size_t handle = 0;
const void* data = nullptr;
@@ -126,7 +131,8 @@
// should be null since we don't create any IPC objects
CHECK(data == nullptr) << data;
},
- [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) {
+ size_t size = provider.ConsumeIntegral<size_t>();
FUZZ_LOG() << "about to readEmbeddedBuffer";
size_t handle = 0;
size_t parent_buffer_handle = 0;
@@ -138,7 +144,8 @@
// should be null since we don't create any IPC objects
CHECK(data == nullptr) << data;
},
- [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) {
+ size_t size = provider.ConsumeIntegral<size_t>();
FUZZ_LOG() << "about to readNullableEmbeddedBuffer";
size_t handle = 0;
size_t parent_buffer_handle = 0;
@@ -150,7 +157,7 @@
// should be null since we don't create any IPC objects
CHECK(data == nullptr) << data;
},
- [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to readNativeHandleNoDup";
const native_handle_t* handle = nullptr;
status_t status = p.readNativeHandleNoDup(&handle);
diff --git a/libs/binder/tests/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp
index f435dae..70c32cb 100644
--- a/libs/binder/tests/parcel_fuzzer/main.cpp
+++ b/libs/binder/tests/parcel_fuzzer/main.cpp
@@ -83,19 +83,14 @@
FUZZ_LOG() << "input: " << HexString(p.data(), p.dataSize());
FUZZ_LOG() << "instructions: " << HexString(instructions.data(), instructions.size());
- for (size_t i = 0; i + 1 < instructions.size(); i += 2) {
- uint8_t a = instructions[i];
- uint8_t readIdx = a % reads.size();
+ FuzzedDataProvider instructionsProvider(instructions.data(), instructions.size());
+ while (instructionsProvider.remaining_bytes() > 0) {
+ uint8_t idx = instructionsProvider.ConsumeIntegralInRange<uint8_t>(0, reads.size() - 1);
- uint8_t b = instructions[i + 1];
+ FUZZ_LOG() << "Instruction " << idx << " avail: " << p.dataAvail()
+ << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity();
- FUZZ_LOG() << "Instruction: " << (i / 2) + 1 << "/" << instructions.size() / 2
- << " cmd: " << static_cast<size_t>(a) << " (" << static_cast<size_t>(readIdx)
- << ") arg: " << static_cast<size_t>(b) << " size: " << p.dataSize()
- << " avail: " << p.dataAvail() << " pos: " << p.dataPosition()
- << " cap: " << p.dataCapacity();
-
- reads[readIdx](p, b);
+ reads[idx](p, instructionsProvider);
}
}
diff --git a/libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h b/libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
index b68a8a9..765a93e 100644
--- a/libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
+++ b/libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
@@ -15,5 +15,9 @@
*/
#pragma once
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include <functional>
+
template <typename P>
-using ParcelRead = std::function<void(const P& p, uint8_t data)>;
+using ParcelRead = std::function<void(const P& p, FuzzedDataProvider& provider)>;
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index ed728dc..4659b96 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -33,7 +33,7 @@
cc_library_headers {
name: "libnativedisplay_headers",
- export_include_dirs: ["include",],
+ export_include_dirs: ["include"],
}
cc_library_shared {
@@ -43,8 +43,6 @@
"include-private",
],
- clang: true,
-
cflags: [
"-Wall",
"-Werror",
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 9286009..f7d2451 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -64,7 +64,7 @@
symbol_file: "libnativewindow.map.txt",
unversioned: true,
override_export_include_dirs: [
- "include"
+ "include",
],
},
export_include_dirs: [
@@ -72,8 +72,6 @@
"include-private",
],
- clang: true,
-
cflags: [
"-Wall",
"-Werror",
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index 4fb0d2e..86f6c7f 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -35,6 +35,7 @@
header_libs: ["bpf_headers"],
shared_libs: [
"libbase",
+ "libbinder",
"libbpf_bcc",
"libcutils",
"libgfxstats",
diff --git a/services/gpuservice/tests/unittests/GpuStatsTest.cpp b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
index 20c8ccf..0baf1f9 100644
--- a/services/gpuservice/tests/unittests/GpuStatsTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuStatsTest.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "gpuservice_unittest"
#include <unistd.h>
+#include <binder/ProcessState.h>
#include <cutils/properties.h>
#include <gmock/gmock.h>
#include <gpustats/GpuStats.h>
@@ -79,6 +80,10 @@
void SetUp() override {
mCpuVulkanVersion = property_get_int32("ro.cpuvulkan.version", 0);
mGlesVersion = property_get_int32("ro.opengles.version", 0);
+
+ // start the thread pool
+ sp<ProcessState> ps(ProcessState::self());
+ ps->startThreadPool();
}
std::unique_ptr<GpuStats> mGpuStats = std::make_unique<GpuStats>();
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index b419d9a..969c8ba 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1488,15 +1488,14 @@
sp<TestInputListener> mFakeListener;
sp<FakeInputReaderPolicy> mFakePolicy;
std::shared_ptr<FakeEventHub> mFakeEventHub;
- std::unique_ptr<InstrumentedInputReader> mReader;
+ sp<InstrumentedInputReader> mReader;
void SetUp() override {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = new TestInputListener();
- mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
- mFakeListener);
+ mReader = sp<InstrumentedInputReader>::make(mFakeEventHub, mFakePolicy, mFakeListener);
}
void TearDown() override {
@@ -2407,15 +2406,14 @@
std::shared_ptr<FakeEventHub> mFakeEventHub;
sp<FakeInputReaderPolicy> mFakePolicy;
sp<TestInputListener> mFakeListener;
- std::unique_ptr<InstrumentedInputReader> mReader;
+ sp<InstrumentedInputReader> mReader;
std::shared_ptr<InputDevice> mDevice;
void SetUp() override {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = new TestInputListener();
- mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
- mFakeListener);
+ mReader = sp<InstrumentedInputReader>::make(mFakeEventHub, mFakePolicy, mFakeListener);
InputDeviceIdentifier identifier;
identifier.name = DEVICE_NAME;
identifier.location = DEVICE_LOCATION;
@@ -2680,15 +2678,14 @@
std::shared_ptr<FakeEventHub> mFakeEventHub;
sp<FakeInputReaderPolicy> mFakePolicy;
sp<TestInputListener> mFakeListener;
- std::unique_ptr<InstrumentedInputReader> mReader;
+ sp<InstrumentedInputReader> mReader;
std::shared_ptr<InputDevice> mDevice;
virtual void SetUp(Flags<InputDeviceClass> classes) {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = new TestInputListener();
- mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
- mFakeListener);
+ mReader = sp<InstrumentedInputReader>::make(mFakeEventHub, mFakePolicy, mFakeListener);
mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
}
@@ -8987,15 +8984,14 @@
std::shared_ptr<FakeEventHub> mFakeEventHub;
sp<FakeInputReaderPolicy> mFakePolicy;
sp<TestInputListener> mFakeListener;
- std::unique_ptr<InstrumentedInputReader> mReader;
+ sp<InstrumentedInputReader> mReader;
std::shared_ptr<InputDevice> mDevice;
virtual void SetUp(Flags<InputDeviceClass> classes) {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = new TestInputListener();
- mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
- mFakeListener);
+ mReader = sp<InstrumentedInputReader>::make(mFakeEventHub, mFakePolicy, mFakeListener);
mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
}