Merge "libbinder fuzzService: can't start threadpool"
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 9186514..fa7be18 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -18,3 +18,9 @@
chmod 0666 /sys/kernel/tracing/events/filemap/enable
chmod 0666 /sys/kernel/debug/tracing/events/filemap/enable
+ # Allow traced_probes to use the raw_syscall filters to trace only a subset
+ # of syscalls.
+ chmod 0666 /sys/kernel/tracing/events/raw_syscalls/sys_enter/filter
+ chmod 0666 /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/filter
+ chmod 0666 /sys/kernel/tracing/events/raw_syscalls/sys_exit/filter
+ chmod 0666 /sys/kernel/debug/tracing/events/raw_syscalls/sys_exit/filter
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 6ee3070..8f163b9 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1955,7 +1955,6 @@
return error("Failed to determine free space for " + data_path);
}
- int64_t cleared = 0;
int64_t needed = targetFreeBytes - free;
if (!defy_target) {
LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested "
@@ -2056,7 +2055,6 @@
// 2. Populate tracker stats and insert into priority queue
ATRACE_BEGIN("populate");
- int64_t cacheTotal = 0;
auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) {
return (left->getCacheRatio() < right->getCacheRatio());
};
@@ -2065,7 +2063,6 @@
for (const auto& it : trackers) {
it.second->loadStats();
queue.push(it.second);
- cacheTotal += it.second->cacheUsed;
}
ATRACE_END();
@@ -2111,7 +2108,6 @@
}
active->cacheUsed -= item->size;
needed -= item->size;
- cleared += item->size;
}
if (!defy_target) {
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 4d9b710..ffc082d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -523,7 +523,6 @@
*/
bool is_valid_package_name(const std::string& packageName) {
// This logic is borrowed from PackageParser.java
- bool hasSep = false;
bool front = true;
auto it = packageName.begin();
@@ -539,7 +538,6 @@
}
}
if (c == '.') {
- hasSep = true;
front = true;
continue;
}
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 25bd9a3..fd879c6 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -90,29 +90,16 @@
cc_fuzz {
name: "servicemanager_fuzzer",
- defaults: ["servicemanager_defaults"],
- host_supported: true,
- static_libs: [
- "libbase",
- "libbinder_random_parcel",
- "libcutils",
+ defaults: [
+ "servicemanager_defaults",
+ "service_fuzzer_defaults",
],
- target: {
- android: {
- shared_libs: [
- "libbinder_ndk",
- "libbinder",
- ],
- },
- host: {
- static_libs: [
- "libbinder_ndk",
- "libbinder",
- ],
- },
- },
+ host_supported: true,
srcs: ["ServiceManagerFuzzer.cpp"],
fuzz_config: {
+ libfuzzer_options: [
+ "max_len=50000",
+ ],
cc: [
"smoreland@google.com",
"waghpawan@google.com",
diff --git a/cmds/servicemanager/ServiceManagerFuzzer.cpp b/cmds/servicemanager/ServiceManagerFuzzer.cpp
index 9e2e53f..39f8522 100644
--- a/cmds/servicemanager/ServiceManagerFuzzer.cpp
+++ b/cmds/servicemanager/ServiceManagerFuzzer.cpp
@@ -26,13 +26,9 @@
using ::android::sp;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- if (size > 50000) {
- return 0;
- }
-
auto accessPtr = std::make_unique<Access>();
auto serviceManager = sp<ServiceManager>::make(std::move(accessPtr));
fuzzService(serviceManager, FuzzedDataProvider(data, size));
return 0;
-}
\ No newline at end of file
+}
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index fabf3eb..5dca468 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -71,15 +71,9 @@
}
cc_defaults {
- name: "libbinder_defaults",
+ name: "libbinder_common_defaults",
host_supported: true,
- // TODO(b/31559095): get headers from bionic on host
- include_dirs: [
- "bionic/libc/kernel/android/uapi/",
- "bionic/libc/kernel/uapi/",
- ],
-
srcs: [
"Binder.cpp",
"BpBinder.cpp",
@@ -87,19 +81,45 @@
"FdTrigger.cpp",
"IInterface.cpp",
"IResultReceiver.cpp",
- "OS.cpp",
"Parcel.cpp",
"ParcelFileDescriptor.cpp",
"RpcSession.cpp",
"RpcServer.cpp",
"RpcState.cpp",
- "RpcTransportRaw.cpp",
"Stability.cpp",
"Status.cpp",
"TextOutput.cpp",
"Utils.cpp",
],
+ shared_libs: [
+ "libcutils",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libbase",
+ ],
+
+ header_libs: [
+ "libbinder_headers",
+ ],
+}
+
+cc_defaults {
+ name: "libbinder_android_defaults",
+
+ // TODO(b/31559095): get headers from bionic on host
+ include_dirs: [
+ "bionic/libc/kernel/android/uapi/",
+ "bionic/libc/kernel/uapi/",
+ ],
+
+ srcs: [
+ "OS.cpp",
+ "RpcTransportRaw.cpp",
+ ],
+
target: {
host: {
srcs: [
@@ -133,16 +153,9 @@
shared_libs: [
"liblog",
- "libcutils",
- "libutils",
- ],
-
- static_libs: [
- "libbase",
],
header_libs: [
- "libbinder_headers",
"libandroid_runtime_vm_headers",
],
@@ -177,6 +190,48 @@
],
}
+cc_library_shared {
+ name: "libbinder_on_trusty_mock",
+ defaults: ["libbinder_common_defaults"],
+
+ srcs: [
+ // Trusty-specific files
+ "trusty/logging.cpp",
+ "trusty/OS.cpp",
+ "trusty/RpcServerTrusty.cpp",
+ "trusty/RpcTransportTipcTrusty.cpp",
+ "trusty/TrustyStatus.cpp",
+ "trusty/socket.cpp",
+ ],
+
+ cflags: [
+ "-DBINDER_RPC_SINGLE_THREADED",
+ // Trusty libbinder uses vendor stability for its binders
+ "-D__ANDROID_VNDK__",
+ "-U__ANDROID__",
+ "-D__TRUSTY__",
+ "-DTRUSTY_USERSPACE",
+ // Flags from the Trusty build system
+ "-Werror",
+ "-Wsign-compare",
+ "-Wno-unused-function",
+ "-Wno-unused-label",
+ "-fno-common",
+ "-fno-omit-frame-pointer",
+ "-fno-threadsafe-statics",
+ ],
+ rtti: false,
+
+ local_include_dirs: [
+ "trusty/include",
+ "trusty/include_mock",
+ ],
+
+ visibility: [
+ ":__subpackages__",
+ ],
+}
+
cc_defaults {
name: "libbinder_kernel_defaults",
srcs: [
@@ -208,7 +263,8 @@
cc_library {
name: "libbinder",
defaults: [
- "libbinder_defaults",
+ "libbinder_common_defaults",
+ "libbinder_android_defaults",
"libbinder_kernel_defaults",
],
@@ -268,7 +324,10 @@
cc_library_static {
name: "libbinder_rpc_no_kernel",
- defaults: ["libbinder_defaults"],
+ defaults: [
+ "libbinder_common_defaults",
+ "libbinder_android_defaults",
+ ],
visibility: [
":__subpackages__",
],
@@ -277,7 +336,8 @@
cc_library_static {
name: "libbinder_rpc_single_threaded",
defaults: [
- "libbinder_defaults",
+ "libbinder_common_defaults",
+ "libbinder_android_defaults",
"libbinder_kernel_defaults",
],
cflags: [
@@ -290,7 +350,10 @@
cc_library_static {
name: "libbinder_rpc_single_threaded_no_kernel",
- defaults: ["libbinder_defaults"],
+ defaults: [
+ "libbinder_common_defaults",
+ "libbinder_android_defaults",
+ ],
cflags: [
"-DBINDER_RPC_SINGLE_THREADED",
],
@@ -446,6 +509,7 @@
// This library is intentionally limited to these targets, and it will be removed later.
// Do not expand the visibility.
visibility: [
+ ":__subpackages__",
"//packages/modules/Virtualization:__subpackages__",
],
}
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index b5ea60f..4029957 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -202,6 +202,17 @@
proxy->withLock(doWithLock);
}
+sp<IBinder> IBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ BBinder* local = localBinder();
+ if (local) {
+ return local->lookupOrCreateWeak(objectID, make, makeArgs);
+ }
+ BpBinder* proxy = this->remoteBinder();
+ LOG_ALWAYS_FATAL_IF(proxy == nullptr, "binder object must be either local or remote");
+ return proxy->lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
// ---------------------------------------------------------------------------
class BBinder::RpcServerLink : public IBinder::DeathRecipient {
@@ -272,11 +283,9 @@
const String16& BBinder::getInterfaceDescriptor() const
{
- // This is a local static rather than a global static,
- // to avoid static initializer ordering issues.
- static String16 sEmptyDescriptor;
- ALOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this);
- return sEmptyDescriptor;
+ static StaticString16 sBBinder(u"BBinder");
+ ALOGW("Reached BBinder::getInterfaceDescriptor (this=%p). Override?", this);
+ return sBBinder;
}
// NOLINTNEXTLINE(google-default-arguments)
@@ -378,6 +387,14 @@
doWithLock();
}
+sp<IBinder> BBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ Extras* e = getOrCreateExtras();
+ LOG_ALWAYS_FATAL_IF(!e, "no memory");
+ AutoMutex _l(e->mLock);
+ return e->mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
BBinder* BBinder::localBinder()
{
return this;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index b6d35ef..d9b7231 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -100,6 +100,36 @@
return value;
}
+namespace {
+struct Tag {
+ wp<IBinder> binder;
+};
+} // namespace
+
+static void cleanWeak(const void* /* id */, void* obj, void* /* cookie */) {
+ delete static_cast<Tag*>(obj);
+}
+
+sp<IBinder> BpBinder::ObjectManager::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ entry_t& e = mObjects[objectID];
+ if (e.object != nullptr) {
+ if (auto attached = static_cast<Tag*>(e.object)->binder.promote()) {
+ return attached;
+ }
+ } else {
+ e.object = new Tag;
+ LOG_ALWAYS_FATAL_IF(!e.object, "no more memory");
+ }
+ sp<IBinder> newObj = make(makeArgs);
+
+ static_cast<Tag*>(e.object)->binder = newObj;
+ e.cleanupCookie = nullptr;
+ e.func = cleanWeak;
+
+ return newObj;
+}
+
void BpBinder::ObjectManager::kill()
{
const size_t N = mObjects.size();
@@ -516,6 +546,12 @@
doWithLock();
}
+sp<IBinder> BpBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ AutoMutex _l(mLock);
+ return mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
BpBinder* BpBinder::remoteBinder()
{
return this;
diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp
index d123fd1..8ee6cb0 100644
--- a/libs/binder/FdTrigger.cpp
+++ b/libs/binder/FdTrigger.cpp
@@ -22,6 +22,7 @@
#include <poll.h>
#include <android-base/macros.h>
+#include <android-base/scopeguard.h>
#include "RpcState.h"
namespace android {
@@ -53,25 +54,34 @@
#endif
}
-status_t FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) {
+status_t FdTrigger::triggerablePoll(const android::RpcTransportFd& transportFd, int16_t event) {
#ifdef BINDER_RPC_SINGLE_THREADED
if (mTriggered) {
return DEAD_OBJECT;
}
#endif
- LOG_ALWAYS_FATAL_IF(event == 0, "triggerablePoll %d with event 0 is not allowed", fd.get());
+ LOG_ALWAYS_FATAL_IF(event == 0, "triggerablePoll %d with event 0 is not allowed",
+ transportFd.fd.get());
pollfd pfd[]{
- {.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
+ {.fd = transportFd.fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
#ifndef BINDER_RPC_SINGLE_THREADED
{.fd = mRead.get(), .events = 0, .revents = 0},
#endif
};
+
+ LOG_ALWAYS_FATAL_IF(transportFd.isInPollingState() == true,
+ "Only one thread should be polling on Fd!");
+
+ transportFd.setPollingState(true);
+ auto pollingStateGuard =
+ android::base::make_scope_guard([&]() { transportFd.setPollingState(false); });
+
int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
if (ret < 0) {
return -errno;
}
- LOG_ALWAYS_FATAL_IF(ret == 0, "poll(%d) returns 0 with infinite timeout", fd.get());
+ LOG_ALWAYS_FATAL_IF(ret == 0, "poll(%d) returns 0 with infinite timeout", transportFd.fd.get());
// At least one FD has events. Check them.
diff --git a/libs/binder/FdTrigger.h b/libs/binder/FdTrigger.h
index a25dc11..5fbf290 100644
--- a/libs/binder/FdTrigger.h
+++ b/libs/binder/FdTrigger.h
@@ -21,6 +21,8 @@
#include <android-base/unique_fd.h>
#include <utils/Errors.h>
+#include <binder/RpcTransport.h>
+
namespace android {
/** This is not a pipe. */
@@ -53,7 +55,8 @@
* true - time to read!
* false - trigger happened
*/
- [[nodiscard]] status_t triggerablePoll(base::borrowed_fd fd, int16_t event);
+ [[nodiscard]] status_t triggerablePoll(const android::RpcTransportFd& transportFd,
+ int16_t event);
private:
#ifdef BINDER_RPC_SINGLE_THREADED
diff --git a/libs/binder/OS.cpp b/libs/binder/OS.cpp
index 6eb7272..24ce2bb 100644
--- a/libs/binder/OS.cpp
+++ b/libs/binder/OS.cpp
@@ -17,6 +17,7 @@
#include "OS.h"
#include <android-base/file.h>
+#include <binder/RpcTransportRaw.h>
#include <string.h>
using android::base::ErrnoError;
@@ -48,4 +49,18 @@
return OK;
}
+status_t dupFileDescriptor(int oldFd, int* newFd) {
+ int ret = fcntl(oldFd, F_DUPFD_CLOEXEC, 0);
+ if (ret < 0) {
+ return -errno;
+ }
+
+ *newFd = ret;
+ return OK;
+}
+
+std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory() {
+ return RpcTransportCtxFactoryRaw::make();
+}
+
} // namespace android
diff --git a/libs/binder/OS.h b/libs/binder/OS.h
index e802e9c..5ab8bab 100644
--- a/libs/binder/OS.h
+++ b/libs/binder/OS.h
@@ -20,6 +20,7 @@
#include <android-base/result.h>
#include <android-base/unique_fd.h>
+#include <binder/RpcTransport.h>
#include <utils/Errors.h>
namespace android {
@@ -28,4 +29,8 @@
status_t getRandomBytes(uint8_t* data, size_t size);
+status_t dupFileDescriptor(int oldFd, int* newFd);
+
+std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory();
+
} // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8b5d118..8887572 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -48,6 +48,7 @@
#include <utils/String8.h>
#include <utils/misc.h>
+#include "OS.h"
#include "RpcState.h"
#include "Static.h"
#include "Utils.h"
@@ -1477,9 +1478,9 @@
status_t Parcel::writeDupFileDescriptor(int fd)
{
- int dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
- if (dupFd < 0) {
- return -errno;
+ int dupFd;
+ if (status_t err = dupFileDescriptor(fd, &dupFd); err != OK) {
+ return err;
}
status_t err = writeFileDescriptor(dupFd, true /*takeOwnership*/);
if (err != OK) {
@@ -1496,9 +1497,9 @@
status_t Parcel::writeDupParcelFileDescriptor(int fd)
{
- int dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
- if (dupFd < 0) {
- return -errno;
+ int dupFd;
+ if (status_t err = dupFileDescriptor(fd, &dupFd); err != OK) {
+ return err;
}
status_t err = writeParcelFileDescriptor(dupFd, true /*takeOwnership*/);
if (err != OK) {
@@ -2295,7 +2296,12 @@
return BAD_TYPE;
}
- val->reset(fcntl(got, F_DUPFD_CLOEXEC, 0));
+ int dupFd;
+ if (status_t err = dupFileDescriptor(got, &dupFd); err != OK) {
+ return BAD_VALUE;
+ }
+
+ val->reset(dupFd);
if (val->get() < 0) {
return BAD_VALUE;
@@ -2312,7 +2318,12 @@
return BAD_TYPE;
}
- val->reset(fcntl(got, F_DUPFD_CLOEXEC, 0));
+ int dupFd;
+ if (status_t err = dupFileDescriptor(got, &dupFd); err != OK) {
+ return BAD_VALUE;
+ }
+
+ val->reset(dupFd);
if (val->get() < 0) {
return BAD_VALUE;
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 49be4dd..0ee5f05 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -55,7 +55,7 @@
sp<RpcServer> RpcServer::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) {
// Default is without TLS.
if (rpcTransportCtxFactory == nullptr)
- rpcTransportCtxFactory = RpcTransportCtxFactoryRaw::make();
+ rpcTransportCtxFactory = makeDefaultRpcTransportCtxFactory();
auto ctx = rpcTransportCtxFactory->newServerCtx();
if (ctx == nullptr) return nullptr;
return sp<RpcServer>::make(std::move(ctx));
@@ -86,7 +86,7 @@
LOG_ALWAYS_FATAL_IF(socketAddress.addr()->sa_family != AF_INET, "expecting inet");
sockaddr_in addr{};
socklen_t len = sizeof(addr);
- if (0 != getsockname(mServer.get(), reinterpret_cast<sockaddr*>(&addr), &len)) {
+ if (0 != getsockname(mServer.fd.get(), reinterpret_cast<sockaddr*>(&addr), &len)) {
int savedErrno = errno;
ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(),
strerror(savedErrno));
@@ -181,7 +181,7 @@
{
RpcMutexLockGuard _l(mLock);
- LOG_ALWAYS_FATAL_IF(!mServer.ok(), "RpcServer must be setup to join.");
+ LOG_ALWAYS_FATAL_IF(!mServer.fd.ok(), "RpcServer must be setup to join.");
LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined");
mJoinThreadRunning = true;
mShutdownTrigger = FdTrigger::make();
@@ -194,24 +194,24 @@
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.data()),
- &addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK)));
+ RpcTransportFd clientSocket(unique_fd(TEMP_FAILURE_RETRY(
+ accept4(mServer.fd.get(), reinterpret_cast<sockaddr*>(addr.data()), &addrLen,
+ SOCK_CLOEXEC | SOCK_NONBLOCK))));
LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(sockaddr_storage)),
"Truncated address");
- if (clientFd < 0) {
+ if (clientSocket.fd < 0) {
ALOGE("Could not accept4 socket: %s", strerror(errno));
continue;
}
- LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
+ LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get());
{
RpcMutexLockGuard _l(mLock);
RpcMaybeThread thread =
RpcMaybeThread(&RpcServer::establishConnection,
- sp<RpcServer>::fromExisting(this), std::move(clientFd), addr,
+ sp<RpcServer>::fromExisting(this), std::move(clientSocket), addr,
addrLen, RpcSession::join);
auto& threadRef = mConnectingThreads[thread.get_id()];
@@ -296,7 +296,7 @@
}
void RpcServer::establishConnection(
- sp<RpcServer>&& server, base::unique_fd clientFd, std::array<uint8_t, kRpcAddressSize> addr,
+ sp<RpcServer>&& server, RpcTransportFd clientFd, std::array<uint8_t, kRpcAddressSize> addr,
size_t addrLen,
std::function<void(sp<RpcSession>&&, RpcSession::PreJoinSetupResult&&)>&& joinFn) {
// mShutdownTrigger can only be cleared once connection threads have joined.
@@ -306,7 +306,7 @@
status_t status = OK;
- int clientFdForLog = clientFd.get();
+ int clientFdForLog = clientFd.fd.get();
auto client = server->mCtx->newTransport(std::move(clientFd), server->mShutdownTrigger.get());
if (client == nullptr) {
ALOGE("Dropping accept4()-ed socket because sslAccept fails");
@@ -488,15 +488,15 @@
LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server.");
- unique_fd serverFd(TEMP_FAILURE_RETRY(
- socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
- if (serverFd == -1) {
+ RpcTransportFd transportFd(unique_fd(TEMP_FAILURE_RETRY(
+ socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))));
+ if (!transportFd.fd.ok()) {
int savedErrno = errno;
ALOGE("Could not create socket: %s", strerror(savedErrno));
return -savedErrno;
}
- if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) {
+ if (0 != TEMP_FAILURE_RETRY(bind(transportFd.fd.get(), addr.addr(), addr.addrSize()))) {
int savedErrno = errno;
ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
return -savedErrno;
@@ -506,7 +506,7 @@
// the backlog is increased to a large number.
// TODO(b/189955605): Once we create threads dynamically & lazily, the backlog can be reduced
// to 1.
- if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 50 /*backlog*/))) {
+ if (0 != TEMP_FAILURE_RETRY(listen(transportFd.fd.get(), 50 /*backlog*/))) {
int savedErrno = errno;
ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
return -savedErrno;
@@ -514,7 +514,7 @@
LOG_RPC_DETAIL("Successfully setup socket server %s", addr.toString().c_str());
- if (status_t status = setupExternalServer(std::move(serverFd)); status != OK) {
+ if (status_t status = setupExternalServer(std::move(transportFd.fd)); status != OK) {
ALOGE("Another thread has set up server while calling setupSocketServer. Race?");
return status;
}
@@ -542,17 +542,17 @@
bool RpcServer::hasServer() {
RpcMutexLockGuard _l(mLock);
- return mServer.ok();
+ return mServer.fd.ok();
}
unique_fd RpcServer::releaseServer() {
RpcMutexLockGuard _l(mLock);
- return std::move(mServer);
+ return std::move(mServer.fd);
}
status_t RpcServer::setupExternalServer(base::unique_fd serverFd) {
RpcMutexLockGuard _l(mLock);
- if (mServer.ok()) {
+ if (mServer.fd.ok()) {
ALOGE("Each RpcServer can only have one server.");
return INVALID_OPERATION;
}
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index d347262..bef2ed6 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -68,7 +68,7 @@
sp<RpcSession> RpcSession::make() {
// Default is without TLS.
- return make(RpcTransportCtxFactoryRaw::make());
+ return make(makeDefaultRpcTransportCtxFactory());
}
sp<RpcSession> RpcSession::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) {
@@ -162,7 +162,8 @@
return NAME_NOT_FOUND;
}
-status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) {
+status_t RpcSession::setupPreconnectedClient(base::unique_fd fd,
+ std::function<unique_fd()>&& request) {
return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) -> status_t {
if (!fd.ok()) {
fd = request();
@@ -172,7 +173,9 @@
ALOGE("setupPreconnectedClient: %s", res.error().message().c_str());
return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code();
}
- status_t status = initAndAddConnection(std::move(fd), sessionId, incoming);
+
+ RpcTransportFd transportFd(std::move(fd));
+ status_t status = initAndAddConnection(std::move(transportFd), sessionId, incoming);
fd = unique_fd(); // Explicitly reset after move to avoid analyzer warning.
return status;
});
@@ -190,7 +193,8 @@
return -savedErrno;
}
- auto server = mCtx->newTransport(std::move(serverFd), mShutdownTrigger.get());
+ RpcTransportFd transportFd(std::move(serverFd));
+ auto server = mCtx->newTransport(std::move(transportFd), mShutdownTrigger.get());
if (server == nullptr) {
ALOGE("Unable to set up RpcTransport");
return UNKNOWN_ERROR;
@@ -484,6 +488,9 @@
mProtocolVersion = oldProtocolVersion;
mConnections = {};
+
+ // clear mStartedSetup so that we can reuse this RpcSession
+ mStartedSetup = false;
});
if (status_t status = connectAndInit({}, false /*incoming*/); status != OK) return status;
@@ -569,12 +576,14 @@
return -savedErrno;
}
- if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
+ RpcTransportFd transportFd(std::move(serverFd));
+
+ if (0 != TEMP_FAILURE_RETRY(connect(transportFd.fd.get(), addr.addr(), addr.addrSize()))) {
int connErrno = errno;
if (connErrno == EAGAIN || connErrno == EINPROGRESS) {
// For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or
// EINPROGRESS (for others). Call poll() and getsockopt() to get the error.
- status_t pollStatus = mShutdownTrigger->triggerablePoll(serverFd, POLLOUT);
+ status_t pollStatus = mShutdownTrigger->triggerablePoll(transportFd, POLLOUT);
if (pollStatus != OK) {
ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
statusToString(pollStatus).c_str());
@@ -582,8 +591,8 @@
}
// Set connErrno to the errno that connect() would have set if the fd were blocking.
socklen_t connErrnoLen = sizeof(connErrno);
- int ret =
- getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &connErrno, &connErrnoLen);
+ int ret = getsockopt(transportFd.fd.get(), SOL_SOCKET, SO_ERROR, &connErrno,
+ &connErrnoLen);
if (ret == -1) {
int savedErrno = errno;
ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s. "
@@ -605,16 +614,17 @@
return -connErrno;
}
}
- LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
+ LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(),
+ transportFd.fd.get());
- return initAndAddConnection(std::move(serverFd), sessionId, incoming);
+ return initAndAddConnection(std::move(transportFd), sessionId, incoming);
}
ALOGE("Ran out of retries to connect to %s", addr.toString().c_str());
return UNKNOWN_ERROR;
}
-status_t RpcSession::initAndAddConnection(unique_fd fd, const std::vector<uint8_t>& sessionId,
+status_t RpcSession::initAndAddConnection(RpcTransportFd fd, const std::vector<uint8_t>& sessionId,
bool incoming) {
LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr);
auto server = mCtx->newTransport(std::move(fd), mShutdownTrigger.get());
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 51326f6..65e8fac 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -36,11 +36,11 @@
// RpcTransport with TLS disabled.
class RpcTransportRaw : public RpcTransport {
public:
- explicit RpcTransportRaw(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
+ explicit RpcTransportRaw(android::RpcTransportFd socket) : mSocket(std::move(socket)) {}
status_t pollRead(void) override {
uint8_t buf;
ssize_t ret = TEMP_FAILURE_RETRY(
- ::recv(mSocket.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT));
+ ::recv(mSocket.fd.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT));
if (ret < 0) {
int savedErrno = errno;
if (savedErrno == EAGAIN || savedErrno == EWOULDBLOCK) {
@@ -100,7 +100,7 @@
msg.msg_controllen = CMSG_SPACE(fdsByteSize);
ssize_t processedSize = TEMP_FAILURE_RETRY(
- sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
+ sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
if (processedSize > 0) {
sentFds = true;
}
@@ -113,10 +113,10 @@
// non-negative int and can be cast to either.
.msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
};
- return TEMP_FAILURE_RETRY(sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
+ return TEMP_FAILURE_RETRY(sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
};
- return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, send, "sendmsg",
- POLLOUT, altPoll);
+ return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, send, "sendmsg", POLLOUT,
+ altPoll);
}
status_t interruptableReadFully(
@@ -135,7 +135,7 @@
.msg_controllen = sizeof(msgControlBuf),
};
ssize_t processSize =
- TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
+ TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
if (processSize < 0) {
return -1;
}
@@ -171,21 +171,23 @@
// non-negative int and can be cast to either.
.msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
};
- return TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
+ return TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
};
- return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, recv, "recvmsg",
- POLLIN, altPoll);
+ return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN,
+ altPoll);
}
+ virtual bool isWaiting() { return mSocket.isInPollingState(); }
+
private:
- base::unique_fd mSocket;
+ android::RpcTransportFd mSocket;
};
// RpcTransportCtx with TLS disabled.
class RpcTransportCtxRaw : public RpcTransportCtx {
public:
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, FdTrigger*) const {
- return std::make_unique<RpcTransportRaw>(std::move(fd));
+ std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd socket, FdTrigger*) const {
+ return std::make_unique<RpcTransportRaw>(std::move(socket));
}
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
};
diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp
index 79983f4..453279c 100644
--- a/libs/binder/RpcTransportTipcAndroid.cpp
+++ b/libs/binder/RpcTransportTipcAndroid.cpp
@@ -36,8 +36,7 @@
// RpcTransport for writing Trusty IPC clients in Android.
class RpcTransportTipcAndroid : public RpcTransport {
public:
- explicit RpcTransportTipcAndroid(android::base::unique_fd socket)
- : mSocket(std::move(socket)) {}
+ explicit RpcTransportTipcAndroid(android::RpcTransportFd socket) : mSocket(std::move(socket)) {}
status_t pollRead() override {
if (mReadBufferPos < mReadBufferSize) {
@@ -46,7 +45,7 @@
}
// Trusty IPC device is not a socket, so MSG_PEEK is not available
- pollfd pfd{.fd = mSocket.get(), .events = static_cast<int16_t>(POLLIN), .revents = 0};
+ pollfd pfd{.fd = mSocket.fd.get(), .events = static_cast<int16_t>(POLLIN), .revents = 0};
ssize_t ret = TEMP_FAILURE_RETRY(::poll(&pfd, 1, 0));
if (ret < 0) {
int savedErrno = errno;
@@ -84,9 +83,9 @@
// to send any.
LOG_ALWAYS_FATAL_IF(ancillaryFds != nullptr && !ancillaryFds->empty(),
"File descriptors are not supported on Trusty yet");
- return TEMP_FAILURE_RETRY(tipc_send(mSocket.get(), iovs, niovs, nullptr, 0));
+ return TEMP_FAILURE_RETRY(tipc_send(mSocket.fd.get(), iovs, niovs, nullptr, 0));
};
- return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, writeFn, "tipc_send",
+ return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, writeFn, "tipc_send",
POLLOUT, altPoll);
}
@@ -103,7 +102,10 @@
// read and call readFn as many times as needed to get all the data
status_t ret = fillReadBuffer();
if (ret != OK) {
- return ret;
+ // We need to emulate a Linux read call, which sets errno on
+ // error and returns -1
+ errno = -ret;
+ return -1;
}
ssize_t processSize = 0;
@@ -117,10 +119,12 @@
return processSize;
};
- return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, readFn, "read",
- POLLIN, altPoll);
+ return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, readFn, "read", POLLIN,
+ altPoll);
}
+ bool isWaiting() override { return mSocket.isInPollingState(); }
+
private:
status_t fillReadBuffer() {
if (mReadBufferPos < mReadBufferSize) {
@@ -143,8 +147,8 @@
mReadBufferSize = 0;
while (true) {
- ssize_t processSize =
- TEMP_FAILURE_RETRY(read(mSocket.get(), mReadBuffer.get(), mReadBufferCapacity));
+ ssize_t processSize = TEMP_FAILURE_RETRY(
+ read(mSocket.fd.get(), mReadBuffer.get(), mReadBufferCapacity));
if (processSize == 0) {
return DEAD_OBJECT;
} else if (processSize < 0) {
@@ -170,7 +174,7 @@
}
}
- base::unique_fd mSocket;
+ RpcTransportFd mSocket;
// For now, we copy all the input data into a temporary buffer because
// we might get multiple interruptableReadFully calls per message, but
@@ -189,7 +193,7 @@
// RpcTransportCtx for Trusty.
class RpcTransportCtxTipcAndroid : public RpcTransportCtx {
public:
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
+ std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd fd,
FdTrigger*) const override {
return std::make_unique<RpcTransportTipcAndroid>(std::move(fd));
}
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
index 09b5c17..3e98ecc 100644
--- a/libs/binder/RpcTransportTls.cpp
+++ b/libs/binder/RpcTransportTls.cpp
@@ -182,8 +182,8 @@
// If |sslError| is WANT_READ / WANT_WRITE, poll for POLLIN / POLLOUT respectively. Otherwise
// return error. Also return error if |fdTrigger| is triggered before or during poll().
status_t pollForSslError(
- android::base::borrowed_fd fd, int sslError, FdTrigger* fdTrigger, const char* fnString,
- int additionalEvent,
+ const android::RpcTransportFd& fd, int sslError, FdTrigger* fdTrigger,
+ const char* fnString, int additionalEvent,
const std::optional<android::base::function_ref<status_t()>>& altPoll) {
switch (sslError) {
case SSL_ERROR_WANT_READ:
@@ -198,7 +198,7 @@
private:
bool mHandled = false;
- status_t handlePoll(int event, android::base::borrowed_fd fd, FdTrigger* fdTrigger,
+ status_t handlePoll(int event, const android::RpcTransportFd& fd, FdTrigger* fdTrigger,
const char* fnString,
const std::optional<android::base::function_ref<status_t()>>& altPoll) {
status_t ret;
@@ -277,7 +277,7 @@
class RpcTransportTls : public RpcTransport {
public:
- RpcTransportTls(android::base::unique_fd socket, Ssl ssl)
+ RpcTransportTls(RpcTransportFd socket, Ssl ssl)
: mSocket(std::move(socket)), mSsl(std::move(ssl)) {}
status_t pollRead(void) override;
status_t interruptableWriteFully(
@@ -290,8 +290,10 @@
const std::optional<android::base::function_ref<status_t()>>& altPoll,
std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override;
+ bool isWaiting() { return mSocket.isInPollingState(); };
+
private:
- android::base::unique_fd mSocket;
+ android::RpcTransportFd mSocket;
Ssl mSsl;
};
@@ -350,7 +352,7 @@
int sslError = mSsl.getError(writeSize);
// TODO(b/195788248): BIO should contain the FdTrigger, and send(2) / recv(2) should be
// triggerablePoll()-ed. Then additionalEvent is no longer necessary.
- status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger,
+ status_t pollStatus = errorQueue.pollForSslError(mSocket, sslError, fdTrigger,
"SSL_write", POLLIN, altPoll);
if (pollStatus != OK) return pollStatus;
// Do not advance buffer. Try SSL_write() again.
@@ -398,7 +400,7 @@
return DEAD_OBJECT;
}
int sslError = mSsl.getError(readSize);
- status_t pollStatus = errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger,
+ status_t pollStatus = errorQueue.pollForSslError(mSocket, sslError, fdTrigger,
"SSL_read", 0, altPoll);
if (pollStatus != OK) return pollStatus;
// Do not advance buffer. Try SSL_read() again.
@@ -409,8 +411,8 @@
}
// For |ssl|, set internal FD to |fd|, and do handshake. Handshake is triggerable by |fdTrigger|.
-bool setFdAndDoHandshake(Ssl* ssl, android::base::borrowed_fd fd, FdTrigger* fdTrigger) {
- bssl::UniquePtr<BIO> bio = newSocketBio(fd);
+bool setFdAndDoHandshake(Ssl* ssl, const android::RpcTransportFd& socket, FdTrigger* fdTrigger) {
+ bssl::UniquePtr<BIO> bio = newSocketBio(socket.fd);
TEST_AND_RETURN(false, bio != nullptr);
auto [_, errorQueue] = ssl->call(SSL_set_bio, bio.get(), bio.get());
(void)bio.release(); // SSL_set_bio takes ownership.
@@ -430,7 +432,7 @@
return false;
}
int sslError = ssl->getError(ret);
- status_t pollStatus = errorQueue.pollForSslError(fd, sslError, fdTrigger,
+ status_t pollStatus = errorQueue.pollForSslError(socket, sslError, fdTrigger,
"SSL_do_handshake", 0, std::nullopt);
if (pollStatus != OK) return false;
}
@@ -442,7 +444,7 @@
typename = std::enable_if_t<std::is_base_of_v<RpcTransportCtxTls, Impl>>>
static std::unique_ptr<RpcTransportCtxTls> create(
std::shared_ptr<RpcCertificateVerifier> verifier, RpcAuth* auth);
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
+ std::unique_ptr<RpcTransport> newTransport(RpcTransportFd fd,
FdTrigger* fdTrigger) const override;
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override;
@@ -513,15 +515,15 @@
return ret;
}
-std::unique_ptr<RpcTransport> RpcTransportCtxTls::newTransport(android::base::unique_fd fd,
+std::unique_ptr<RpcTransport> RpcTransportCtxTls::newTransport(android::RpcTransportFd socket,
FdTrigger* fdTrigger) const {
bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get()));
TEST_AND_RETURN(nullptr, ssl != nullptr);
Ssl wrapped(std::move(ssl));
preHandshake(&wrapped);
- TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, fd, fdTrigger));
- return std::make_unique<RpcTransportTls>(std::move(fd), std::move(wrapped));
+ TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, socket, fdTrigger));
+ return std::make_unique<RpcTransportTls>(std::move(socket), std::move(wrapped));
}
class RpcTransportCtxTlsServer : public RpcTransportCtxTls {
diff --git a/libs/binder/RpcTransportUtils.h b/libs/binder/RpcTransportUtils.h
index 00cb2af..32f0db8 100644
--- a/libs/binder/RpcTransportUtils.h
+++ b/libs/binder/RpcTransportUtils.h
@@ -25,8 +25,8 @@
template <typename SendOrReceive>
status_t interruptableReadOrWrite(
- int socketFd, FdTrigger* fdTrigger, iovec* iovs, int niovs, SendOrReceive sendOrReceiveFun,
- const char* funName, int16_t event,
+ const android::RpcTransportFd& socket, FdTrigger* fdTrigger, iovec* iovs, int niovs,
+ SendOrReceive sendOrReceiveFun, const char* funName, int16_t event,
const std::optional<android::base::function_ref<status_t()>>& altPoll) {
MAYBE_WAIT_IN_FLAKE_MODE;
@@ -99,7 +99,7 @@
return DEAD_OBJECT;
}
} else {
- if (status_t status = fdTrigger->triggerablePoll(socketFd, event); status != OK)
+ if (status_t status = fdTrigger->triggerablePoll(socket, event); status != OK)
return status;
if (!havePolled) havePolled = true;
}
diff --git a/libs/binder/binder_module.h b/libs/binder/binder_module.h
index 7574c29..793795e 100644
--- a/libs/binder/binder_module.h
+++ b/libs/binder/binder_module.h
@@ -100,23 +100,4 @@
#define BINDER_ENABLE_ONEWAY_SPAM_DETECTION _IOW('b', 16, __u32)
#endif // BINDER_ENABLE_ONEWAY_SPAM_DETECTION
-#ifndef BINDER_GET_EXTENDED_ERROR
-/* struct binder_extened_error - extended error information
- * @id: identifier for the failed operation
- * @command: command as defined by binder_driver_return_protocol
- * @param: parameter holding a negative errno value
- *
- * Used with BINDER_GET_EXTENDED_ERROR. This extends the error information
- * returned by the driver upon a failed operation. Userspace can pull this
- * data to properly handle specific error scenarios.
- */
-struct binder_extended_error {
- __u32 id;
- __u32 command;
- __s32 param;
-};
-
-#define BINDER_GET_EXTENDED_ERROR _IOWR('b', 17, struct binder_extended_error)
-#endif // BINDER_GET_EXTENDED_ERROR
-
#endif // _BINDER_MODULE_H_
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 46223bb..88d9ca1 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -59,6 +59,8 @@
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
void withLock(const std::function<void()>& doWithLock);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
virtual BBinder* localBinder();
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 19ad5e6..4172cc5 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -72,6 +72,8 @@
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
void withLock(const std::function<void()>& doWithLock);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
virtual BpBinder* remoteBinder();
@@ -96,6 +98,8 @@
IBinder::object_cleanup_func func);
void* find(const void* objectID) const;
void* detach(const void* objectID);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
void kill();
@@ -104,9 +108,9 @@
ObjectManager& operator=(const ObjectManager&);
struct entry_t {
- void* object;
- void* cleanupCookie;
- IBinder::object_cleanup_func func;
+ void* object = nullptr;
+ void* cleanupCookie = nullptr;
+ IBinder::object_cleanup_func func = nullptr;
};
std::map<const void*, entry_t> mObjects;
diff --git a/libs/binder/include/binder/Delegate.h b/libs/binder/include/binder/Delegate.h
new file mode 100644
index 0000000..8b3fc1c
--- /dev/null
+++ b/libs/binder/include/binder/Delegate.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 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
+
+#include <binder/IBinder.h>
+
+#ifndef __BIONIC__
+#ifndef __assert
+
+// defined differently by liblog
+#pragma push_macro("LOG_PRI")
+#ifdef LOG_PRI
+#undef LOG_PRI
+#endif
+#include <syslog.h>
+#pragma pop_macro("LOG_PRI")
+
+#define __assert(a, b, c) \
+ do { \
+ syslog(LOG_ERR, a ": " c); \
+ abort(); \
+ } while (false)
+#endif // __assert
+#endif // __BIONIC__
+
+namespace android {
+
+/*
+ * Used to manage AIDL's *Delegator types.
+ * This is used to:
+ * - create a new *Delegator object that delegates to the binder argument.
+ * - or return an existing *Delegator object that already delegates to the
+ * binder argument.
+ * - or return the underlying delegate binder if the binder argument is a
+ * *Delegator itself.
+ *
+ * @param binder - the binder to delegate to or unwrap
+ *
+ * @return pointer to the *Delegator object or the unwrapped binder object
+ */
+template <typename T>
+sp<T> delegate(const sp<T>& binder) {
+ const void* isDelegatorId = &T::descriptor;
+ const void* hasDelegatorId = &T::descriptor + 1;
+ // is binder itself a delegator?
+ if (T::asBinder(binder)->findObject(isDelegatorId)) {
+ if (T::asBinder(binder)->findObject(hasDelegatorId)) {
+ __assert(__FILE__, __LINE__,
+ "This binder has a delegator and is also delegator itself! This is "
+ "likely an unintended mixing of binders.");
+ return nullptr;
+ }
+ // unwrap the delegator
+ return static_cast<typename T::DefaultDelegator*>(binder.get())->getImpl();
+ }
+
+ struct MakeArgs {
+ const sp<T>* binder;
+ const void* id;
+ } makeArgs;
+ makeArgs.binder = &binder;
+ makeArgs.id = isDelegatorId;
+
+ // the binder is not a delegator, so construct one
+ sp<IBinder> newDelegator = T::asBinder(binder)->lookupOrCreateWeak(
+ hasDelegatorId,
+ [](const void* args) -> sp<IBinder> {
+ auto delegator = sp<typename T::DefaultDelegator>::make(
+ *static_cast<const MakeArgs*>(args)->binder);
+ // make sure we know this binder is a delegator by attaching a unique ID
+ (void)delegator->attachObject(static_cast<const MakeArgs*>(args)->id,
+ reinterpret_cast<void*>(0x1), nullptr, nullptr);
+ return delegator;
+ },
+ static_cast<const void*>(&makeArgs));
+ return sp<typename T::DefaultDelegator>::cast(newDelegator);
+}
+
+} // namespace android
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 43fc5ff..83aaca7 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -284,6 +284,9 @@
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
+ typedef sp<IBinder> (*object_make_func)(const void* makeArgs);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs);
protected:
virtual ~IBinder();
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 52bda0e..ca02ab2 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -199,7 +199,7 @@
static constexpr size_t kRpcAddressSize = 128;
static void establishConnection(
- sp<RpcServer>&& server, base::unique_fd clientFd,
+ sp<RpcServer>&& server, RpcTransportFd clientFd,
std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen,
std::function<void(sp<RpcSession>&&, RpcSession::PreJoinSetupResult&&)>&& joinFn);
[[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address);
@@ -210,7 +210,7 @@
// A mode is supported if the N'th bit is on, where N is the mode enum's value.
std::bitset<8> mSupportedFileDescriptorTransportModes = std::bitset<8>().set(
static_cast<size_t>(RpcSession::FileDescriptorTransportMode::NONE));
- base::unique_fd mServer; // socket we are accepting sessions on
+ RpcTransportFd mServer; // socket we are accepting sessions on
RpcMutex mLock; // for below
std::unique_ptr<RpcMaybeThread> mJoinThread;
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 428e272..9630e2f 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -269,7 +269,7 @@
[[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address,
const std::vector<uint8_t>& sessionId,
bool incoming);
- [[nodiscard]] status_t initAndAddConnection(base::unique_fd fd,
+ [[nodiscard]] status_t initAndAddConnection(RpcTransportFd fd,
const std::vector<uint8_t>& sessionId,
bool incoming);
[[nodiscard]] status_t addIncomingConnection(std::unique_ptr<RpcTransport> rpcTransport);
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index 5197ef9..fd52a3a 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -30,12 +30,14 @@
#include <utils/Errors.h>
#include <binder/RpcCertificateFormat.h>
+#include <binder/RpcThreads.h>
#include <sys/uio.h>
namespace android {
class FdTrigger;
+struct RpcTransportFd;
// Represents a socket connection.
// No thread-safety is guaranteed for these APIs.
@@ -81,6 +83,15 @@
const std::optional<android::base::function_ref<status_t()>> &altPoll,
std::vector<std::variant<base::unique_fd, base::borrowed_fd>> *ancillaryFds) = 0;
+ /**
+ * Check whether any threads are blocked while polling the transport
+ * for read operations
+ * Return:
+ * True - Specifies that there is active polling on transport.
+ * False - No active polling on transport
+ */
+ [[nodiscard]] virtual bool isWaiting() = 0;
+
protected:
RpcTransport() = default;
};
@@ -96,7 +107,7 @@
// Implementation details: for TLS, this function may incur I/O. |fdTrigger| may be used
// to interrupt I/O. This function blocks until handshake is finished.
[[nodiscard]] virtual std::unique_ptr<RpcTransport> newTransport(
- android::base::unique_fd fd, FdTrigger *fdTrigger) const = 0;
+ android::RpcTransportFd fd, FdTrigger *fdTrigger) const = 0;
// Return the preconfigured certificate of this context.
//
@@ -129,4 +140,36 @@
RpcTransportCtxFactory() = default;
};
+struct RpcTransportFd {
+private:
+ mutable bool isPolling{false};
+
+ void setPollingState(bool state) const { isPolling = state; }
+
+public:
+ base::unique_fd fd;
+
+ RpcTransportFd() = default;
+ explicit RpcTransportFd(base::unique_fd &&descriptor)
+ : isPolling(false), fd(std::move(descriptor)) {}
+
+ RpcTransportFd(RpcTransportFd &&transportFd) noexcept
+ : isPolling(transportFd.isPolling), fd(std::move(transportFd.fd)) {}
+
+ RpcTransportFd &operator=(RpcTransportFd &&transportFd) noexcept {
+ fd = std::move(transportFd.fd);
+ isPolling = transportFd.isPolling;
+ return *this;
+ }
+
+ RpcTransportFd &operator=(base::unique_fd &&descriptor) noexcept {
+ fd = std::move(descriptor);
+ isPolling = false;
+ return *this;
+ }
+
+ bool isInPollingState() const { return isPolling; }
+ friend class FdTrigger;
+};
+
} // namespace android
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
index f45aa76..c1f2620 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
@@ -58,6 +58,9 @@
#endif
AParcel_appendFrom(other.mParcel.get(), this->mParcel.get(), 0,
AParcel_getDataSize(other.mParcel.get()));
+ } else {
+ syslog(LOG_ERR,
+ "sdk_version not compatible, AParcelableHolder need sdk_version >= 31!");
}
}
#endif
@@ -192,6 +195,9 @@
if (__ANDROID_API__ >= 31) {
#endif
AParcel_reset(mParcel.get());
+ } else {
+ syslog(LOG_ERR,
+ "sdk_version not compatible, AParcelableHolder need sdk_version >= 31!");
}
}
@@ -201,6 +207,29 @@
inline bool operator==(const AParcelableHolder& rhs) const { return this == &rhs; }
inline bool operator>(const AParcelableHolder& rhs) const { return this > &rhs; }
inline bool operator>=(const AParcelableHolder& rhs) const { return this >= &rhs; }
+#if __ANDROID_API__ >= 31
+ inline AParcelableHolder& operator=(const AParcelableHolder& rhs) {
+ // AParcelableHolder has been introduced in 31.
+#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__
+ if (__builtin_available(android 31, *)) {
+#else
+ if (__ANDROID_API__ >= 31) {
+#endif
+ this->reset();
+ if (this->mStability != rhs.mStability) {
+ syslog(LOG_ERR, "AParcelableHolder stability mismatch: this %d rhs %d!",
+ this->mStability, rhs.mStability);
+ abort();
+ }
+ AParcel_appendFrom(rhs.mParcel.get(), this->mParcel.get(), 0,
+ AParcel_getDataSize(rhs.mParcel.get()));
+ } else {
+ syslog(LOG_ERR,
+ "sdk_version not compatible, AParcelableHolder need sdk_version >= 31!");
+ }
+ return *this;
+ }
+#endif
private:
mutable ndk::ScopedAParcel mParcel;
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index c0d4487..0ec6183 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -144,24 +144,6 @@
min_sdk_version: "Tiramisu",
}
-// TODO(b/184872979): remove once the Rust API is created.
-rust_bindgen {
- name: "libbinder_rpc_unstable_bindgen",
- wrapper_src: ":libbinder_rpc_unstable_header",
- crate_name: "binder_rpc_unstable_bindgen",
- visibility: ["//packages/modules/Virtualization:__subpackages__"],
- source_stem: "bindings",
- shared_libs: [
- "libutils",
- ],
- apex_available: [
- "com.android.compos",
- "com.android.uwb",
- "com.android.virt",
- ],
- min_sdk_version: "Tiramisu",
-}
-
rust_test {
name: "libbinder_rs-internal_test",
crate_name: "binder",
@@ -188,13 +170,3 @@
clippy_lints: "none",
lints: "none",
}
-
-rust_test {
- name: "libbinder_rpc_unstable_bindgen_test",
- srcs: [":libbinder_rpc_unstable_bindgen"],
- crate_name: "binder_rpc_unstable_bindgen",
- test_suites: ["general-tests"],
- auto_gen_config: true,
- clippy_lints: "none",
- lints: "none",
-}
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
new file mode 100644
index 0000000..f169390
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -0,0 +1,59 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+rust_library {
+ name: "librpcbinder_rs",
+ crate_name: "rpcbinder",
+ srcs: ["src/lib.rs"],
+ shared_libs: [
+ "libutils",
+ ],
+ rustlibs: [
+ "libbinder_ndk_sys",
+ "libbinder_rpc_unstable_bindgen",
+ "libbinder_rs",
+ "libdowncast_rs",
+ "liblibc",
+ ],
+ apex_available: [
+ "com.android.compos",
+ "com.android.uwb",
+ "com.android.virt",
+ ],
+ min_sdk_version: "Tiramisu",
+}
+
+// TODO(b/184872979): remove once the RPC Binder API is stabilised.
+rust_bindgen {
+ name: "libbinder_rpc_unstable_bindgen",
+ wrapper_src: ":libbinder_rpc_unstable_header",
+ crate_name: "binder_rpc_unstable_bindgen",
+ visibility: [":__subpackages__"],
+ source_stem: "bindings",
+ shared_libs: [
+ "libbinder_rpc_unstable",
+ "libutils",
+ ],
+ apex_available: [
+ "com.android.compos",
+ "com.android.uwb",
+ "com.android.virt",
+ ],
+ min_sdk_version: "Tiramisu",
+}
+
+rust_test {
+ name: "libbinder_rpc_unstable_bindgen_test",
+ srcs: [":libbinder_rpc_unstable_bindgen"],
+ crate_name: "binder_rpc_unstable_bindgen",
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ clippy_lints: "none",
+ lints: "none",
+}
diff --git a/libs/binder/rust/rpcbinder/src/client.rs b/libs/binder/rust/rpcbinder/src/client.rs
new file mode 100644
index 0000000..dfc6f06
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/src/client.rs
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+use binder::{
+ unstable_api::{new_spibinder, AIBinder},
+ FromIBinder, SpIBinder, StatusCode, Strong,
+};
+use std::os::{
+ raw::{c_int, c_void},
+ unix::io::RawFd,
+};
+
+/// Connects to an RPC Binder server over vsock.
+pub fn get_vsock_rpc_service(cid: u32, port: u32) -> Option<SpIBinder> {
+ // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can
+ // safely be taken by new_spibinder.
+ unsafe { new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, port) as *mut AIBinder) }
+}
+
+/// Connects to an RPC Binder server for a particular interface over vsock.
+pub fn get_vsock_rpc_interface<T: FromIBinder + ?Sized>(
+ cid: u32,
+ port: u32,
+) -> Result<Strong<T>, StatusCode> {
+ interface_cast(get_vsock_rpc_service(cid, port))
+}
+
+/// Connects to an RPC Binder server, using the given callback to get (and take ownership of)
+/// file descriptors already connected to it.
+pub fn get_preconnected_rpc_service(
+ mut request_fd: impl FnMut() -> Option<RawFd>,
+) -> Option<SpIBinder> {
+ // Double reference the factory because trait objects aren't FFI safe.
+ let mut request_fd_ref: RequestFd = &mut request_fd;
+ let param = &mut request_fd_ref as *mut RequestFd as *mut c_void;
+
+ // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the
+ // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership
+ // of param, only passing it to request_fd_wrapper.
+ unsafe {
+ new_spibinder(binder_rpc_unstable_bindgen::RpcPreconnectedClient(
+ Some(request_fd_wrapper),
+ param,
+ ) as *mut AIBinder)
+ }
+}
+
+type RequestFd<'a> = &'a mut dyn FnMut() -> Option<RawFd>;
+
+unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int {
+ // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the
+ // BinderFdFactory reference, with param being a properly aligned non-null pointer to an
+ // initialized instance.
+ let request_fd_ptr = param as *mut RequestFd;
+ let request_fd = request_fd_ptr.as_mut().unwrap();
+ if let Some(fd) = request_fd() {
+ fd
+ } else {
+ -1
+ }
+}
+
+/// Connects to an RPC Binder server for a particular interface, using the given callback to get
+/// (and take ownership of) file descriptors already connected to it.
+pub fn get_preconnected_rpc_interface<T: FromIBinder + ?Sized>(
+ request_fd: impl FnMut() -> Option<RawFd>,
+) -> Result<Strong<T>, StatusCode> {
+ interface_cast(get_preconnected_rpc_service(request_fd))
+}
+
+fn interface_cast<T: FromIBinder + ?Sized>(
+ service: Option<SpIBinder>,
+) -> Result<Strong<T>, StatusCode> {
+ if let Some(service) = service {
+ FromIBinder::try_from(service)
+ } else {
+ Err(StatusCode::NAME_NOT_FOUND)
+ }
+}
diff --git a/libs/binder/rust/rpcbinder/src/lib.rs b/libs/binder/rust/rpcbinder/src/lib.rs
new file mode 100644
index 0000000..a5eea61
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/src/lib.rs
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+//! API for RPC Binder services.
+
+mod client;
+mod server;
+
+pub use client::{
+ get_preconnected_rpc_interface, get_preconnected_rpc_service, get_vsock_rpc_interface,
+ get_vsock_rpc_service,
+};
+pub use server::{run_rpc_server, run_rpc_server_with_factory};
diff --git a/libs/binder/rust/rpcbinder/src/server.rs b/libs/binder/rust/rpcbinder/src/server.rs
new file mode 100644
index 0000000..d98a439
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/src/server.rs
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+use binder::{unstable_api::AsNative, SpIBinder};
+use std::{os::raw, ptr::null_mut};
+
+/// Runs a binder RPC server, serving the supplied binder service implementation on the given vsock
+/// port.
+///
+/// If and when the server is ready for connections (it is listening on the port), `on_ready` is
+/// called to allow appropriate action to be taken - e.g. to notify clients that they may now
+/// attempt to connect.
+///
+/// The current thread is joined to the binder thread pool to handle incoming messages.
+///
+/// Returns true if the server has shutdown normally, false if it failed in some way.
+pub fn run_rpc_server<F>(service: SpIBinder, port: u32, on_ready: F) -> bool
+where
+ F: FnOnce(),
+{
+ let mut ready_notifier = ReadyNotifier(Some(on_ready));
+ ready_notifier.run_server(service, port)
+}
+
+struct ReadyNotifier<F>(Option<F>)
+where
+ F: FnOnce();
+
+impl<F> ReadyNotifier<F>
+where
+ F: FnOnce(),
+{
+ fn run_server(&mut self, mut service: SpIBinder, port: u32) -> bool {
+ let service = service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder;
+ let param = self.as_void_ptr();
+
+ // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
+ // Plus the binder objects are threadsafe.
+ // RunRpcServerCallback does not retain a reference to `ready_callback` or `param`; it only
+ // uses them before it returns, which is during the lifetime of `self`.
+ unsafe {
+ binder_rpc_unstable_bindgen::RunRpcServerCallback(
+ service,
+ port,
+ Some(Self::ready_callback),
+ param,
+ )
+ }
+ }
+
+ fn as_void_ptr(&mut self) -> *mut raw::c_void {
+ self as *mut _ as *mut raw::c_void
+ }
+
+ unsafe extern "C" fn ready_callback(param: *mut raw::c_void) {
+ // SAFETY: This is only ever called by `RunRpcServerCallback`, within the lifetime of the
+ // `ReadyNotifier`, with `param` taking the value returned by `as_void_ptr` (so a properly
+ // aligned non-null pointer to an initialized instance).
+ let ready_notifier = param as *mut Self;
+ ready_notifier.as_mut().unwrap().notify()
+ }
+
+ fn notify(&mut self) {
+ if let Some(on_ready) = self.0.take() {
+ on_ready();
+ }
+ }
+}
+
+type RpcServerFactoryRef<'a> = &'a mut (dyn FnMut(u32) -> Option<SpIBinder> + Send + Sync);
+
+/// Runs a binder RPC server, using the given factory function to construct a binder service
+/// implementation for each connection.
+///
+/// The current thread is joined to the binder thread pool to handle incoming messages.
+///
+/// Returns true if the server has shutdown normally, false if it failed in some way.
+pub fn run_rpc_server_with_factory(
+ port: u32,
+ mut factory: impl FnMut(u32) -> Option<SpIBinder> + Send + Sync,
+) -> bool {
+ // Double reference the factory because trait objects aren't FFI safe.
+ // NB: The type annotation is necessary to ensure that we have a `dyn` rather than an `impl`.
+ let mut factory_ref: RpcServerFactoryRef = &mut factory;
+ let context = &mut factory_ref as *mut RpcServerFactoryRef as *mut raw::c_void;
+
+ // SAFETY: `factory_wrapper` is only ever called by `RunRpcServerWithFactory`, with context
+ // taking the pointer value above (so a properly aligned non-null pointer to an initialized
+ // `RpcServerFactoryRef`), within the lifetime of `factory_ref` (i.e. no more calls will be made
+ // after `RunRpcServerWithFactory` returns).
+ unsafe {
+ binder_rpc_unstable_bindgen::RunRpcServerWithFactory(Some(factory_wrapper), context, port)
+ }
+}
+
+unsafe extern "C" fn factory_wrapper(
+ cid: u32,
+ context: *mut raw::c_void,
+) -> *mut binder_rpc_unstable_bindgen::AIBinder {
+ // SAFETY: `context` was created from an `&mut RpcServerFactoryRef` by
+ // `run_rpc_server_with_factory`, and we are still within the lifetime of the value it is
+ // pointing to.
+ let factory_ptr = context as *mut RpcServerFactoryRef;
+ let factory = factory_ptr.as_mut().unwrap();
+
+ if let Some(mut service) = factory(cid) {
+ service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder
+ } else {
+ null_mut()
+ }
+}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index d7c6d49..e460d2c 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -341,6 +341,11 @@
"binderRpcTest_shared_defaults",
"libbinder_tls_shared_deps",
],
+
+ // Add the Trusty mock library as a fake dependency so it gets built
+ required: [
+ "libbinder_on_trusty_mock",
+ ],
}
cc_test {
@@ -684,3 +689,37 @@
],
test_suites: ["general-tests"],
}
+
+cc_defaults {
+ name: "service_fuzzer_defaults",
+ static_libs: [
+ "libbase",
+ "libbinder_random_parcel",
+ "libcutils",
+ ],
+ target: {
+ android: {
+ shared_libs: [
+ "libbinder_ndk",
+ "libbinder",
+ "libutils",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libbinder_ndk",
+ "libbinder",
+ "libutils",
+ ],
+ },
+ darwin: {
+ enabled: false,
+ },
+ },
+ fuzz_config: {
+ cc: [
+ "smoreland@google.com",
+ "waghpawan@google.com",
+ ],
+ },
+}
diff --git a/libs/binder/tests/binderBinderUnitTest.cpp b/libs/binder/tests/binderBinderUnitTest.cpp
index ce2770f..b6aed0d 100644
--- a/libs/binder/tests/binderBinderUnitTest.cpp
+++ b/libs/binder/tests/binderBinderUnitTest.cpp
@@ -15,10 +15,11 @@
*/
#include <binder/Binder.h>
-#include <binder/IBinder.h>
+#include <binder/IInterface.h>
#include <gtest/gtest.h>
using android::BBinder;
+using android::IBinder;
using android::OK;
using android::sp;
@@ -48,3 +49,49 @@
binder->setExtension(ext);
EXPECT_EQ(ext, binder->getExtension());
}
+
+struct MyCookie {
+ bool* deleted;
+};
+
+class UniqueBinder : public BBinder {
+public:
+ UniqueBinder(const void* c) : cookie(reinterpret_cast<const MyCookie*>(c)) {
+ *cookie->deleted = false;
+ }
+ ~UniqueBinder() { *cookie->deleted = true; }
+ const MyCookie* cookie;
+};
+
+static sp<IBinder> make(const void* arg) {
+ return sp<UniqueBinder>::make(arg);
+}
+
+TEST(Binder, LookupOrCreateWeak) {
+ auto binder = sp<BBinder>::make();
+ bool deleted;
+ MyCookie cookie = {&deleted};
+ sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie);
+ EXPECT_NE(binder, createdBinder);
+
+ sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie);
+ EXPECT_EQ(createdBinder, lookedUpBinder);
+ EXPECT_FALSE(deleted);
+}
+
+TEST(Binder, LookupOrCreateWeakDropSp) {
+ auto binder = sp<BBinder>::make();
+ bool deleted1 = false;
+ bool deleted2 = false;
+ MyCookie cookie1 = {&deleted1};
+ MyCookie cookie2 = {&deleted2};
+ sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie1);
+ EXPECT_NE(binder, createdBinder);
+
+ createdBinder.clear();
+ EXPECT_TRUE(deleted1);
+
+ sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie2);
+ EXPECT_EQ(&cookie2, sp<UniqueBinder>::cast(lookedUpBinder)->cookie);
+ EXPECT_FALSE(deleted2);
+}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index e72f39c..5de08bd 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -1158,6 +1158,42 @@
EXPECT_EQ(readValue, testValue);
}
+// see ProcessState.cpp BINDER_VM_SIZE = 1MB.
+// This value is not exposed, but some code in the framework relies on being able to use
+// buffers near the cap size.
+// TODO(b/238777741): why do larger values, like 300K fail sometimes
+constexpr size_t kSizeBytesAlmostFull = 100'000;
+constexpr size_t kSizeBytesOverFull = 1'050'000;
+
+TEST_F(BinderLibTest, GargantuanVectorSent) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+
+ for (size_t i = 0; i < 10; i++) {
+ // a slight variation in size is used to consider certain possible caching implementations
+ const std::vector<uint64_t> testValue((kSizeBytesAlmostFull + i) / sizeof(uint64_t), 42);
+
+ Parcel data, reply;
+ data.writeUint64Vector(testValue);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply), StatusEq(NO_ERROR))
+ << i;
+ std::vector<uint64_t> readValue;
+ EXPECT_THAT(reply.readUint64Vector(&readValue), StatusEq(OK));
+ EXPECT_EQ(readValue, testValue);
+ }
+}
+
+TEST_F(BinderLibTest, LimitExceededVectorSent) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+ const std::vector<uint64_t> testValue(kSizeBytesOverFull / sizeof(uint64_t), 42);
+
+ Parcel data, reply;
+ data.writeUint64Vector(testValue);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply),
+ StatusEq(FAILED_TRANSACTION));
+}
+
TEST_F(BinderLibTest, BufRejected) {
Parcel data, reply;
uint32_t buf;
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 501a604..21b0354 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -54,27 +54,6 @@
EXPECT_DEATH(p.markForBinder(sp<BBinder>::make()), "format must be set before data is written");
}
-class BinderRpcServerOnly : public ::testing::TestWithParam<std::tuple<RpcSecurity, uint32_t>> {
-public:
- static std::string PrintTestParam(const ::testing::TestParamInfo<ParamType>& info) {
- return std::string(newFactory(std::get<0>(info.param))->toCString()) + "_serverV" +
- std::to_string(std::get<1>(info.param));
- }
-};
-
-TEST_P(BinderRpcServerOnly, SetExternalServerTest) {
- base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)));
- int sinkFd = sink.get();
- auto server = RpcServer::make(newFactory(std::get<0>(GetParam())));
- server->setProtocolVersion(std::get<1>(GetParam()));
- ASSERT_FALSE(server->hasServer());
- ASSERT_EQ(OK, server->setupExternalServer(std::move(sink)));
- ASSERT_TRUE(server->hasServer());
- base::unique_fd retrieved = server->releaseServer();
- ASSERT_FALSE(server->hasServer());
- ASSERT_EQ(sinkFd, retrieved.get());
-}
-
TEST(BinderRpc, CannotUseNextWireVersion) {
auto session = RpcSession::make();
EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT));
@@ -264,9 +243,13 @@
RpcSecurity rpcSecurity() const { return std::get<1>(GetParam()); }
uint32_t clientVersion() const { return std::get<2>(GetParam()); }
uint32_t serverVersion() const { return std::get<3>(GetParam()); }
- bool singleThreaded() const { return std::get<4>(GetParam()); }
+ bool serverSingleThreaded() const { return std::get<4>(GetParam()); }
bool noKernel() const { return std::get<5>(GetParam()); }
+ bool clientOrServerSingleThreaded() const {
+ return !kEnableRpcThreads || serverSingleThreaded();
+ }
+
// Whether the test params support sending FDs in parcels.
bool supportsFdTransport() const {
return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
@@ -404,18 +387,6 @@
size_t sleepMs = 500);
};
-// Test fixture for tests that start multiple threads.
-// This includes tests with one thread but multiple sessions,
-// since a server uses one thread per session.
-class BinderRpcThreads : public BinderRpc {
-public:
- void SetUp() override {
- if constexpr (!kEnableRpcThreads) {
- GTEST_SKIP() << "Test skipped because threads were disabled at build time";
- }
- }
-};
-
TEST_P(BinderRpc, Ping) {
auto proc = createRpcTestSocketServerProcess({});
ASSERT_NE(proc.rootBinder, nullptr);
@@ -428,7 +399,13 @@
EXPECT_EQ(IBinderRpcTest::descriptor, proc.rootBinder->getInterfaceDescriptor());
}
-TEST_P(BinderRpcThreads, MultipleSessions) {
+TEST_P(BinderRpc, MultipleSessions) {
+ if (serverSingleThreaded()) {
+ // Tests with multiple sessions require a multi-threaded service,
+ // but work fine on a single-threaded client
+ GTEST_SKIP() << "This test requires a multi-threaded service";
+ }
+
auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 5});
for (auto session : proc.proc.sessions) {
ASSERT_NE(nullptr, session.root);
@@ -436,7 +413,11 @@
}
}
-TEST_P(BinderRpcThreads, SeparateRootObject) {
+TEST_P(BinderRpc, SeparateRootObject) {
+ if (serverSingleThreaded()) {
+ GTEST_SKIP() << "This test requires a multi-threaded service";
+ }
+
SocketType type = std::get<0>(GetParam());
if (type == SocketType::PRECONNECTED || type == SocketType::UNIX) {
// we can't get port numbers for unix sockets
@@ -619,7 +600,11 @@
proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError());
}
-TEST_P(BinderRpcThreads, CannotMixBindersBetweenTwoSessionsToTheSameServer) {
+TEST_P(BinderRpc, CannotMixBindersBetweenTwoSessionsToTheSameServer) {
+ if (serverSingleThreaded()) {
+ GTEST_SKIP() << "This test requires a multi-threaded service";
+ }
+
auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 2});
sp<IBinder> outBinder;
@@ -775,7 +760,11 @@
return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}
-TEST_P(BinderRpcThreads, ThreadPoolGreaterThanEqualRequested) {
+TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumThreads = 10;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
@@ -826,14 +815,22 @@
EXPECT_LE(epochMsAfter, epochMsBefore + 3 * sleepMs);
}
-TEST_P(BinderRpcThreads, ThreadPoolOverSaturated) {
+TEST_P(BinderRpc, ThreadPoolOverSaturated) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumThreads = 10;
constexpr size_t kNumCalls = kNumThreads + 3;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
testThreadPoolOverSaturated(proc.rootIface, kNumCalls);
}
-TEST_P(BinderRpcThreads, ThreadPoolLimitOutgoing) {
+TEST_P(BinderRpc, ThreadPoolLimitOutgoing) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumThreads = 20;
constexpr size_t kNumOutgoingConnections = 10;
constexpr size_t kNumCalls = kNumOutgoingConnections + 3;
@@ -842,7 +839,11 @@
testThreadPoolOverSaturated(proc.rootIface, kNumCalls);
}
-TEST_P(BinderRpcThreads, ThreadingStressTest) {
+TEST_P(BinderRpc, ThreadingStressTest) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumClientThreads = 10;
constexpr size_t kNumServerThreads = 10;
constexpr size_t kNumCalls = 100;
@@ -871,7 +872,11 @@
for (auto& t : threads) t.join();
}
-TEST_P(BinderRpcThreads, OnewayStressTest) {
+TEST_P(BinderRpc, OnewayStressTest) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumClientThreads = 10;
constexpr size_t kNumServerThreads = 10;
constexpr size_t kNumCalls = 1000;
@@ -906,7 +911,11 @@
EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs);
}
-TEST_P(BinderRpcThreads, OnewayCallQueueing) {
+TEST_P(BinderRpc, OnewayCallQueueing) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumSleeps = 10;
constexpr size_t kNumExtraServerThreads = 4;
constexpr size_t kSleepMs = 50;
@@ -935,7 +944,11 @@
saturateThreadPool(1 + kNumExtraServerThreads, proc.rootIface);
}
-TEST_P(BinderRpcThreads, OnewayCallExhaustion) {
+TEST_P(BinderRpc, OnewayCallExhaustion) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumClients = 2;
constexpr size_t kTooLongMs = 1000;
@@ -978,17 +991,16 @@
TEST_P(BinderRpc, Callbacks) {
const static std::string kTestString = "good afternoon!";
- bool bothSingleThreaded = !kEnableRpcThreads || singleThreaded();
-
for (bool callIsOneway : {true, false}) {
for (bool callbackIsOneway : {true, false}) {
for (bool delayed : {true, false}) {
- if (bothSingleThreaded && (callIsOneway || callbackIsOneway || delayed)) {
+ if (clientOrServerSingleThreaded() &&
+ (callIsOneway || callbackIsOneway || delayed)) {
// we have no incoming connections to receive the callback
continue;
}
- size_t numIncomingConnections = bothSingleThreaded ? 0 : 1;
+ size_t numIncomingConnections = clientOrServerSingleThreaded() ? 0 : 1;
auto proc = createRpcTestSocketServerProcess(
{.numThreads = 1,
.numSessions = 1,
@@ -1036,7 +1048,7 @@
}
TEST_P(BinderRpc, SingleDeathRecipient) {
- if (singleThreaded() || !kEnableRpcThreads) {
+ if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
class MyDeathRec : public IBinder::DeathRecipient {
@@ -1062,10 +1074,7 @@
}
std::unique_lock<std::mutex> lock(dr->mMtx);
- if (!dr->dead) {
- EXPECT_EQ(std::cv_status::no_timeout, dr->mCv.wait_for(lock, 1000ms));
- }
- EXPECT_TRUE(dr->dead) << "Failed to receive the death notification.";
+ ASSERT_TRUE(dr->mCv.wait_for(lock, 1000ms, [&]() { return dr->dead; }));
// need to wait for the session to shutdown so we don't "Leak session"
EXPECT_TRUE(proc.proc.sessions.at(0).session->shutdownAndWait(true));
@@ -1073,7 +1082,7 @@
}
TEST_P(BinderRpc, SingleDeathRecipientOnShutdown) {
- if (singleThreaded() || !kEnableRpcThreads) {
+ if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
class MyDeathRec : public IBinder::DeathRecipient {
@@ -1127,7 +1136,7 @@
}
TEST_P(BinderRpc, UnlinkDeathRecipient) {
- if (singleThreaded() || !kEnableRpcThreads) {
+ if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
class MyDeathRec : public IBinder::DeathRecipient {
@@ -1193,7 +1202,7 @@
// libbinder.so (when using static libraries, even a client and service
// using the same kind of static library should have separate copies of the
// variables).
- if (!kEnableSharedLibs || singleThreaded() || noKernel()) {
+ if (!kEnableSharedLibs || serverSingleThreaded() || noKernel()) {
GTEST_SKIP() << "Test disabled because Binder kernel driver was disabled "
"at build time.";
}
@@ -1393,7 +1402,11 @@
return ret;
}
-TEST_P(BinderRpcThreads, Fds) {
+TEST_P(BinderRpc, Fds) {
+ if (serverSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
ssize_t beforeFds = countFds();
ASSERT_GE(beforeFds, 0);
{
@@ -1534,15 +1547,6 @@
::testing::Values(false, true)),
BinderRpc::PrintParamInfo);
-INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpcThreads,
- ::testing::Combine(::testing::ValuesIn(testSocketTypes()),
- ::testing::ValuesIn(RpcSecurityValues()),
- ::testing::ValuesIn(testVersions()),
- ::testing::ValuesIn(testVersions()),
- ::testing::Values(false),
- ::testing::Values(false, true)),
- BinderRpc::PrintParamInfo);
-
class BinderRpcServerRootObject
: public ::testing::TestWithParam<std::tuple<bool, bool, RpcSecurity>> {};
@@ -1594,36 +1598,6 @@
bool mValue = false;
};
-TEST_P(BinderRpcServerOnly, Shutdown) {
- if constexpr (!kEnableRpcThreads) {
- GTEST_SKIP() << "Test skipped because threads were disabled at build time";
- }
-
- auto addr = allocateSocketAddress();
- auto server = RpcServer::make(newFactory(std::get<0>(GetParam())));
- server->setProtocolVersion(std::get<1>(GetParam()));
- ASSERT_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
- auto joinEnds = std::make_shared<OneOffSignal>();
-
- // If things are broken and the thread never stops, don't block other tests. Because the thread
- // may run after the test finishes, it must not access the stack memory of the test. Hence,
- // shared pointers are passed.
- std::thread([server, joinEnds] {
- server->join();
- joinEnds->notify();
- }).detach();
-
- bool shutdown = false;
- for (int i = 0; i < 10 && !shutdown; i++) {
- usleep(300 * 1000); // 300ms; total 3s
- if (server->shutdown()) shutdown = true;
- }
- ASSERT_TRUE(shutdown) << "server->shutdown() never returns true";
-
- ASSERT_TRUE(joinEnds->wait(2s))
- << "After server->shutdown() returns true, join() did not stop after 2s";
-}
-
TEST(BinderRpc, Java) {
#if !defined(__ANDROID__)
GTEST_SKIP() << "This test is only run on Android. Though it can technically run on host on"
@@ -1676,6 +1650,57 @@
ASSERT_EQ(OK, rpcBinder->pingBinder());
}
+class BinderRpcServerOnly : public ::testing::TestWithParam<std::tuple<RpcSecurity, uint32_t>> {
+public:
+ static std::string PrintTestParam(const ::testing::TestParamInfo<ParamType>& info) {
+ return std::string(newFactory(std::get<0>(info.param))->toCString()) + "_serverV" +
+ std::to_string(std::get<1>(info.param));
+ }
+};
+
+TEST_P(BinderRpcServerOnly, SetExternalServerTest) {
+ base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)));
+ int sinkFd = sink.get();
+ auto server = RpcServer::make(newFactory(std::get<0>(GetParam())));
+ server->setProtocolVersion(std::get<1>(GetParam()));
+ ASSERT_FALSE(server->hasServer());
+ ASSERT_EQ(OK, server->setupExternalServer(std::move(sink)));
+ ASSERT_TRUE(server->hasServer());
+ base::unique_fd retrieved = server->releaseServer();
+ ASSERT_FALSE(server->hasServer());
+ ASSERT_EQ(sinkFd, retrieved.get());
+}
+
+TEST_P(BinderRpcServerOnly, Shutdown) {
+ if constexpr (!kEnableRpcThreads) {
+ GTEST_SKIP() << "Test skipped because threads were disabled at build time";
+ }
+
+ auto addr = allocateSocketAddress();
+ auto server = RpcServer::make(newFactory(std::get<0>(GetParam())));
+ server->setProtocolVersion(std::get<1>(GetParam()));
+ ASSERT_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
+ auto joinEnds = std::make_shared<OneOffSignal>();
+
+ // If things are broken and the thread never stops, don't block other tests. Because the thread
+ // may run after the test finishes, it must not access the stack memory of the test. Hence,
+ // shared pointers are passed.
+ std::thread([server, joinEnds] {
+ server->join();
+ joinEnds->notify();
+ }).detach();
+
+ bool shutdown = false;
+ for (int i = 0; i < 10 && !shutdown; i++) {
+ usleep(300 * 1000); // 300ms; total 3s
+ if (server->shutdown()) shutdown = true;
+ }
+ ASSERT_TRUE(shutdown) << "server->shutdown() never returns true";
+
+ ASSERT_TRUE(joinEnds->wait(2s))
+ << "After server->shutdown() returns true, join() did not stop after 2s";
+}
+
INSTANTIATE_TEST_CASE_P(BinderRpc, BinderRpcServerOnly,
::testing::Combine(::testing::ValuesIn(RpcSecurityValues()),
::testing::ValuesIn(testVersions())),
@@ -1748,7 +1773,7 @@
}
}
mFd = rpcServer->releaseServer();
- if (!mFd.ok()) return AssertionFailure() << "releaseServer returns invalid fd";
+ if (!mFd.fd.ok()) return AssertionFailure() << "releaseServer returns invalid fd";
mCtx = newFactory(rpcSecurity, mCertVerifier, std::move(auth))->newServerCtx();
if (mCtx == nullptr) return AssertionFailure() << "newServerCtx";
mSetup = true;
@@ -1769,7 +1794,7 @@
std::vector<std::thread> threads;
while (OK == mFdTrigger->triggerablePoll(mFd, POLLIN)) {
base::unique_fd acceptedFd(
- TEMP_FAILURE_RETRY(accept4(mFd.get(), nullptr, nullptr /*length*/,
+ TEMP_FAILURE_RETRY(accept4(mFd.fd.get(), nullptr, nullptr /*length*/,
SOCK_CLOEXEC | SOCK_NONBLOCK)));
threads.emplace_back(&Server::handleOne, this, std::move(acceptedFd));
}
@@ -1778,7 +1803,8 @@
}
void handleOne(android::base::unique_fd acceptedFd) {
ASSERT_TRUE(acceptedFd.ok());
- auto serverTransport = mCtx->newTransport(std::move(acceptedFd), mFdTrigger.get());
+ RpcTransportFd transportFd(std::move(acceptedFd));
+ auto serverTransport = mCtx->newTransport(std::move(transportFd), mFdTrigger.get());
if (serverTransport == nullptr) return; // handshake failed
ASSERT_TRUE(mPostConnect(serverTransport.get(), mFdTrigger.get()));
}
@@ -1797,7 +1823,7 @@
std::unique_ptr<std::thread> mThread;
ConnectToServer mConnectToServer;
std::unique_ptr<FdTrigger> mFdTrigger = FdTrigger::make();
- base::unique_fd mFd;
+ RpcTransportFd mFd;
std::unique_ptr<RpcTransportCtx> mCtx;
std::shared_ptr<RpcCertificateVerifierSimple> mCertVerifier =
std::make_shared<RpcCertificateVerifierSimple>();
@@ -1844,7 +1870,7 @@
// connect() and do handshake
bool setUpTransport() {
mFd = mConnectToServer();
- if (!mFd.ok()) return AssertionFailure() << "Cannot connect to server";
+ if (!mFd.fd.ok()) return AssertionFailure() << "Cannot connect to server";
mClientTransport = mCtx->newTransport(std::move(mFd), mFdTrigger.get());
return mClientTransport != nullptr;
}
@@ -1873,9 +1899,11 @@
ASSERT_EQ(readOk, readMessage());
}
+ bool isTransportWaiting() { return mClientTransport->isWaiting(); }
+
private:
ConnectToServer mConnectToServer;
- base::unique_fd mFd;
+ RpcTransportFd mFd;
std::unique_ptr<FdTrigger> mFdTrigger = FdTrigger::make();
std::unique_ptr<RpcTransportCtx> mCtx;
std::shared_ptr<RpcCertificateVerifierSimple> mCertVerifier =
@@ -2122,6 +2150,56 @@
ASSERT_FALSE(client.readMessage(msg2));
}
+TEST_P(RpcTransportTest, CheckWaitingForRead) {
+ std::mutex readMutex;
+ std::condition_variable readCv;
+ bool shouldContinueReading = false;
+ // Server will write data on transport once its started
+ auto serverPostConnect = [&](RpcTransport* serverTransport, FdTrigger* fdTrigger) {
+ std::string message(RpcTransportTestUtils::kMessage);
+ iovec messageIov{message.data(), message.size()};
+ auto status = serverTransport->interruptableWriteFully(fdTrigger, &messageIov, 1,
+ std::nullopt, nullptr);
+ if (status != OK) return AssertionFailure() << statusToString(status);
+
+ {
+ std::unique_lock<std::mutex> lock(readMutex);
+ shouldContinueReading = true;
+ lock.unlock();
+ readCv.notify_all();
+ }
+ return AssertionSuccess();
+ };
+
+ // Setup Server and client
+ auto server = std::make_unique<Server>();
+ ASSERT_TRUE(server->setUp(GetParam()));
+
+ Client client(server->getConnectToServerFn());
+ ASSERT_TRUE(client.setUp(GetParam()));
+
+ ASSERT_EQ(OK, trust(&client, server));
+ ASSERT_EQ(OK, trust(server, &client));
+ server->setPostConnect(serverPostConnect);
+
+ server->start();
+ ASSERT_TRUE(client.setUpTransport());
+ {
+ // Wait till server writes data
+ std::unique_lock<std::mutex> lock(readMutex);
+ ASSERT_TRUE(readCv.wait_for(lock, 3s, [&] { return shouldContinueReading; }));
+ }
+
+ // Since there is no read polling here, we will get polling count 0
+ ASSERT_FALSE(client.isTransportWaiting());
+ ASSERT_TRUE(client.readMessage(RpcTransportTestUtils::kMessage));
+ // Thread should increment polling count, read and decrement polling count
+ // Again, polling count should be zero here
+ ASSERT_FALSE(client.isTransportWaiting());
+
+ server->shutdown();
+}
+
INSTANTIATE_TEST_CASE_P(BinderRpc, RpcTransportTest,
::testing::ValuesIn(RpcTransportTest::getRpcTranportTestParams()),
RpcTransportTest::PrintParamInfo);
diff --git a/libs/binder/tests/parcel_fuzzer/random_fd.cpp b/libs/binder/tests/parcel_fuzzer/random_fd.cpp
index 3fcf104..e4dbb2d 100644
--- a/libs/binder/tests/parcel_fuzzer/random_fd.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_fd.cpp
@@ -26,9 +26,12 @@
using base::unique_fd;
std::vector<unique_fd> getRandomFds(FuzzedDataProvider* provider) {
+ const char* fdType;
+
std::vector<unique_fd> fds = provider->PickValueInArray<
std::function<std::vector<unique_fd>()>>({
[&]() {
+ fdType = "ashmem";
std::vector<unique_fd> ret;
ret.push_back(unique_fd(
ashmem_create_region("binder test region",
@@ -36,18 +39,21 @@
return ret;
},
[&]() {
+ fdType = "/dev/null";
std::vector<unique_fd> ret;
ret.push_back(unique_fd(open("/dev/null", O_RDWR)));
return ret;
},
[&]() {
+ fdType = "pipefd";
+
int pipefds[2];
int flags = O_CLOEXEC;
if (provider->ConsumeBool()) flags |= O_DIRECT;
if (provider->ConsumeBool()) flags |= O_NONBLOCK;
- CHECK_EQ(0, pipe2(pipefds, flags));
+ CHECK_EQ(0, pipe2(pipefds, flags)) << flags;
if (provider->ConsumeBool()) std::swap(pipefds[0], pipefds[1]);
@@ -58,7 +64,7 @@
},
})();
- for (const auto& fd : fds) CHECK(fd.ok()) << fd.get();
+ for (const auto& fd : fds) CHECK(fd.ok()) << fd.get() << " " << fdType;
return fds;
}
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index 187add4..46346bb 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -14,7 +14,13 @@
* limitations under the License.
*/
+#if defined(TRUSTY_USERSPACE)
#include <openssl/rand.h>
+#else
+#include <lib/rand/rand.h>
+#endif
+
+#include <binder/RpcTransportTipcTrusty.h>
#include "../OS.h"
@@ -22,14 +28,28 @@
namespace android {
-Result<void> setNonBlocking(android::base::borrowed_fd fd) {
+Result<void> setNonBlocking(android::base::borrowed_fd /*fd*/) {
// Trusty IPC syscalls are all non-blocking by default.
return {};
}
status_t getRandomBytes(uint8_t* data, size_t size) {
+#if defined(TRUSTY_USERSPACE)
int res = RAND_bytes(data, size);
return res == 1 ? OK : UNKNOWN_ERROR;
+#else
+ int res = rand_get_bytes(data, size);
+ return res == 0 ? OK : UNKNOWN_ERROR;
+#endif // TRUSTY_USERSPACE
+}
+
+status_t dupFileDescriptor(int /*oldFd*/, int* /*newFd*/) {
+ // TODO: implement separately
+ return INVALID_OPERATION;
+}
+
+std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory() {
+ return RpcTransportCtxFactoryTipcTrusty::make();
}
} // namespace android
diff --git a/libs/binder/trusty/README.md b/libs/binder/trusty/README.md
index 1a273aa..8a60af8 100644
--- a/libs/binder/trusty/README.md
+++ b/libs/binder/trusty/README.md
@@ -1,39 +1,45 @@
# Binder for Trusty
This is the Trusty port of the libbinder library.
-To build it, take the following steps:
-
-* Check out copies of the Trusty and AOSP repositories.
-* Apply the patches from the `trusty_binder` topic on both repositories.
-* Build Trusty normally using `build.py`.
-* Run the sample AIDL test for Trusty:
- ```shell
- $ ./build-root/.../run --headless --boot-test com.android.trusty.aidl.test
- ```
-
-To run the Android-Trusty IPC test, do the following:
-
-* Build AOSP for the `qemu_trusty_arm64-userdebug` target:
- ```shell
- $ lunch qemu_trusty_arm64-userdebug
- $ m
- ```
-* In the Trusty directory, run the emulator with the newly built Android:
- ```shell
- $ ./build-root/.../run --android /path/to/aosp
- ```
-* Using either `adb` or the shell inside the emulator itself, run the Trusty
- Binder test as root:
- ```shell
- # /data/nativetest64/vendor/trusty_binder_test/trusty_binder_test
- ```
-
-## Running the AIDL compiler
-For now, you will need to run the AIDL compiler manually to generate the C++
-source code for Trusty clients and services. The general syntax is:
+To build it, first you will need a checkout of the Trusty tree:
```shell
-$ aidl --lang=cpp -o <output directory> -h <output header directory> <AIDL files...>
+$ mkdir /path/to/trusty
+$ cd /path/to/trusty
+$ repo init -u https://android.googlesource.com/trusty/manifest -b master
+$ repo sync -j$(nproc) -c --no-tags
```
-The compiler will emit some `.cpp` files in the output directory and their
-corresponding `.h` files in the header directory.
+After the checkout is complete, you can use the `build.py` script for both
+building and testing Trusty. For a quick build without any tests, run:
+```shell
+$ ./trusty/vendor/google/aosp/scripts/build.py generic-arm64-test-debug
+```
+This will build the smaller `generic-arm64-test-debug` project which
+does not run any tests.
+
+The qemu-generic-arm64-test-debug` project includes the QEMU emulator and
+a full Trusty test suite, including a set of libbinder tests.
+To run the latter, use the command:
+```shell
+$ ./trusty/vendor/google/aosp/scripts/build.py \
+ --test "boot-test:com.android.trusty.binder.test" \
+ qemu-generic-arm64-test-debug
+```
+
+## Building AIDL files on Trusty
+To compile AIDL interfaces into Trusty libraries, include the `make/aidl.mk`
+in your `rules.mk` file, e.g.:
+```
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_AIDLS := \
+ $(LOCAL_DIR)/IFoo.aidl \
+
+include make/aidl.mk
+```
+
+## Examples
+The Trusty tree contains some sample test apps at
+`trusty/user/app/sample/binder-test`.
diff --git a/libs/binder/trusty/RpcServerTrusty.cpp b/libs/binder/trusty/RpcServerTrusty.cpp
index e8b91e7..18ce316 100644
--- a/libs/binder/trusty/RpcServerTrusty.cpp
+++ b/libs/binder/trusty/RpcServerTrusty.cpp
@@ -104,24 +104,40 @@
return;
}
- /* Save the session for easy access */
- *ctx_p = session.get();
+ /* Save the session and connection for the other callbacks */
+ auto* channelContext = new (std::nothrow) ChannelContext;
+ if (channelContext == nullptr) {
+ rc = ERR_NO_MEMORY;
+ return;
+ }
+
+ channelContext->session = std::move(session);
+ channelContext->connection = std::move(result.connection);
+
+ *ctx_p = channelContext;
};
base::unique_fd clientFd(chan);
+ android::RpcTransportFd transportFd(std::move(clientFd));
+
std::array<uint8_t, RpcServer::kRpcAddressSize> addr;
constexpr size_t addrLen = sizeof(*peer);
memcpy(addr.data(), peer, addrLen);
- RpcServer::establishConnection(sp(server->mRpcServer), std::move(clientFd), addr, addrLen,
+ RpcServer::establishConnection(sp(server->mRpcServer), std::move(transportFd), addr, addrLen,
joinFn);
return rc;
}
-int RpcServerTrusty::handleMessage(const tipc_port* port, handle_t chan, void* ctx) {
- auto* session = reinterpret_cast<RpcSession*>(ctx);
- status_t status = session->state()->drainCommands(session->mConnections.mIncoming[0], session,
- RpcState::CommandType::ANY);
+int RpcServerTrusty::handleMessage(const tipc_port* /*port*/, handle_t /*chan*/, void* ctx) {
+ auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
+ LOG_ALWAYS_FATAL_IF(channelContext == nullptr,
+ "bad state: message received on uninitialized channel");
+
+ auto& session = channelContext->session;
+ auto& connection = channelContext->connection;
+ status_t status =
+ session->state()->drainCommands(connection, session, RpcState::CommandType::ANY);
if (status != OK) {
LOG_RPC_DETAIL("Binder connection thread closing w/ status %s",
statusToString(status).c_str());
@@ -130,13 +146,21 @@
return NO_ERROR;
}
-void RpcServerTrusty::handleDisconnect(const tipc_port* port, handle_t chan, void* ctx) {}
+void RpcServerTrusty::handleDisconnect(const tipc_port* /*port*/, handle_t /*chan*/,
+ void* /*ctx*/) {}
void RpcServerTrusty::handleChannelCleanup(void* ctx) {
- auto* session = reinterpret_cast<RpcSession*>(ctx);
- auto& connection = session->mConnections.mIncoming.at(0);
+ auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
+ if (channelContext == nullptr) {
+ return;
+ }
+
+ auto& session = channelContext->session;
+ auto& connection = channelContext->connection;
LOG_ALWAYS_FATAL_IF(!session->removeIncomingConnection(connection),
"bad state: connection object guaranteed to be in list");
+
+ delete channelContext;
}
} // namespace android
diff --git a/libs/binder/trusty/RpcTransportTipcTrusty.cpp b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
index dc27eb9..0b67b9f 100644
--- a/libs/binder/trusty/RpcTransportTipcTrusty.cpp
+++ b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
@@ -33,7 +33,7 @@
// RpcTransport for Trusty.
class RpcTransportTipcTrusty : public RpcTransport {
public:
- explicit RpcTransportTipcTrusty(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
+ explicit RpcTransportTipcTrusty(android::RpcTransportFd socket) : mSocket(std::move(socket)) {}
~RpcTransportTipcTrusty() { releaseMessage(); }
status_t pollRead() override {
@@ -45,9 +45,9 @@
}
status_t interruptableWriteFully(
- FdTrigger* fdTrigger, iovec* iovs, int niovs,
- const std::optional<android::base::function_ref<status_t()>>& altPoll,
- const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds)
+ FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs,
+ const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/,
+ const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/)
override {
if (niovs < 0) {
return BAD_VALUE;
@@ -64,7 +64,7 @@
.num_handles = 0, // TODO: add ancillaryFds
.handles = nullptr,
};
- ssize_t rc = send_msg(mSocket.get(), &msg);
+ ssize_t rc = send_msg(mSocket.fd.get(), &msg);
if (rc == ERR_NOT_ENOUGH_BUFFER) {
// Peer is blocked, wait until it unblocks.
// TODO: when tipc supports a send-unblocked handler,
@@ -72,7 +72,7 @@
// when the handler gets called by the library
uevent uevt;
do {
- rc = ::wait(mSocket.get(), &uevt, INFINITE_TIME);
+ rc = ::wait(mSocket.fd.get(), &uevt, INFINITE_TIME);
if (rc < 0) {
return statusFromTrusty(rc);
}
@@ -83,7 +83,7 @@
// Retry the send, it should go through this time because
// sending is now unblocked
- rc = send_msg(mSocket.get(), &msg);
+ rc = send_msg(mSocket.fd.get(), &msg);
}
if (rc < 0) {
return statusFromTrusty(rc);
@@ -95,9 +95,10 @@
}
status_t interruptableReadFully(
- FdTrigger* fdTrigger, iovec* iovs, int niovs,
- const std::optional<android::base::function_ref<status_t()>>& altPoll,
- std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override {
+ FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs,
+ const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/,
+ std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/)
+ override {
if (niovs < 0) {
return BAD_VALUE;
}
@@ -129,7 +130,7 @@
.num_handles = 0, // TODO: support ancillaryFds
.handles = nullptr,
};
- ssize_t rc = read_msg(mSocket.get(), mMessageInfo.id, mMessageOffset, &msg);
+ ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg);
if (rc < 0) {
return statusFromTrusty(rc);
}
@@ -169,6 +170,8 @@
}
}
+ bool isWaiting() override { return mSocket.isInPollingState(); }
+
private:
status_t ensureMessage(bool wait) {
int rc;
@@ -179,7 +182,7 @@
/* TODO: interruptible wait, maybe with a timeout??? */
uevent uevt;
- rc = ::wait(mSocket.get(), &uevt, wait ? INFINITE_TIME : 0);
+ rc = ::wait(mSocket.fd.get(), &uevt, wait ? INFINITE_TIME : 0);
if (rc < 0) {
if (rc == ERR_TIMED_OUT && !wait) {
// If we timed out with wait==false, then there's no message
@@ -192,7 +195,7 @@
return OK;
}
- rc = get_msg(mSocket.get(), &mMessageInfo);
+ rc = get_msg(mSocket.fd.get(), &mMessageInfo);
if (rc < 0) {
return statusFromTrusty(rc);
}
@@ -204,12 +207,12 @@
void releaseMessage() {
if (mHaveMessage) {
- put_msg(mSocket.get(), mMessageInfo.id);
+ put_msg(mSocket.fd.get(), mMessageInfo.id);
mHaveMessage = false;
}
}
- base::unique_fd mSocket;
+ android::RpcTransportFd mSocket;
bool mHaveMessage = false;
ipc_msg_info mMessageInfo;
@@ -219,9 +222,9 @@
// RpcTransportCtx for Trusty.
class RpcTransportCtxTipcTrusty : public RpcTransportCtx {
public:
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
+ std::unique_ptr<RpcTransport> newTransport(android::RpcTransportFd socket,
FdTrigger*) const override {
- return std::make_unique<RpcTransportTipcTrusty>(std::move(fd));
+ return std::make_unique<RpcTransportTipcTrusty>(std::move(socket));
}
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
};
diff --git a/libs/binder/trusty/include/binder/RpcServerTrusty.h b/libs/binder/trusty/include/binder/RpcServerTrusty.h
index e8fc9f9..cc31c95 100644
--- a/libs/binder/trusty/include/binder/RpcServerTrusty.h
+++ b/libs/binder/trusty/include/binder/RpcServerTrusty.h
@@ -77,6 +77,12 @@
explicit RpcServerTrusty(std::unique_ptr<RpcTransportCtx> ctx, std::string&& portName,
std::shared_ptr<const PortAcl>&& portAcl, size_t msgMaxSize);
+ // The Rpc-specific context maintained for every open TIPC channel.
+ struct ChannelContext {
+ sp<RpcSession> session;
+ sp<RpcSession::RpcConnection> connection;
+ };
+
static int handleConnect(const tipc_port* port, handle_t chan, const uuid* peer, void** ctx_p);
static int handleMessage(const tipc_port* port, handle_t chan, void* ctx);
static void handleDisconnect(const tipc_port* port, handle_t chan, void* ctx);
diff --git a/libs/binder/trusty/include_mock/lib/tipc/tipc_srv.h b/libs/binder/trusty/include_mock/lib/tipc/tipc_srv.h
new file mode 100644
index 0000000..2747314
--- /dev/null
+++ b/libs/binder/trusty/include_mock/lib/tipc/tipc_srv.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 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
+
+#include <stddef.h>
+#include <trusty_ipc.h>
+#include <uapi/trusty_uuid.h>
+
+struct tipc_port_acl {
+ uint32_t flags;
+ uint32_t uuid_num;
+ const struct uuid** uuids;
+ const void* extra_data;
+};
+
+struct tipc_port {
+ const char* name;
+ uint32_t msg_max_size;
+ uint32_t msg_queue_len;
+ const struct tipc_port_acl* acl;
+ const void* priv;
+};
+
+struct tipc_srv_ops {
+ int (*on_connect)(const struct tipc_port* port, handle_t chan, const struct uuid* peer,
+ void** ctx_p);
+
+ int (*on_message)(const struct tipc_port* port, handle_t chan, void* ctx);
+
+ void (*on_disconnect)(const struct tipc_port* port, handle_t chan, void* ctx);
+
+ void (*on_channel_cleanup)(void* ctx);
+};
+
+static inline int tipc_add_service(struct tipc_hset*, const struct tipc_port*, uint32_t, uint32_t,
+ const struct tipc_srv_ops*) {
+ return 0;
+}
diff --git a/libs/binder/trusty/include_mock/openssl/rand.h b/libs/binder/trusty/include_mock/openssl/rand.h
new file mode 100644
index 0000000..07dcc1c
--- /dev/null
+++ b/libs/binder/trusty/include_mock/openssl/rand.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 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
+
+static inline int RAND_bytes(unsigned char*, int) {
+ return 0;
+}
diff --git a/libs/binder/trusty/include_mock/trusty_ipc.h b/libs/binder/trusty/include_mock/trusty_ipc.h
new file mode 100644
index 0000000..a2170ce
--- /dev/null
+++ b/libs/binder/trusty/include_mock/trusty_ipc.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 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
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <uapi/trusty_uuid.h>
+
+#define INFINITE_TIME 1
+#define IPC_MAX_MSG_HANDLES 8
+
+#define IPC_HANDLE_POLL_HUP 0x1
+#define IPC_HANDLE_POLL_MSG 0x2
+#define IPC_HANDLE_POLL_SEND_UNBLOCKED 0x4
+
+typedef int handle_t;
+
+typedef struct ipc_msg {
+ uint32_t num_iov;
+ iovec* iov;
+ uint32_t num_handles;
+ handle_t* handles;
+} ipc_msg_t;
+
+typedef struct ipc_msg_info {
+ size_t len;
+ uint32_t id;
+ uint32_t num_handles;
+} ipc_msg_info_t;
+
+typedef struct uevent {
+ uint32_t event;
+} uevent_t;
+
+static inline handle_t port_create(const char*, uint32_t, uint32_t, uint32_t) {
+ return 0;
+}
+static inline handle_t connect(const char*, uint32_t) {
+ return 0;
+}
+static inline handle_t accept(handle_t, uuid_t*) {
+ return 0;
+}
+static inline int set_cookie(handle_t, void*) {
+ return 0;
+}
+static inline handle_t handle_set_create(void) {
+ return 0;
+}
+static inline int handle_set_ctrl(handle_t, uint32_t, struct uevent*) {
+ return 0;
+}
+static inline int wait(handle_t, uevent_t*, uint32_t) {
+ return 0;
+}
+static inline int wait_any(uevent_t*, uint32_t) {
+ return 0;
+}
+static inline int get_msg(handle_t, ipc_msg_info_t*) {
+ return 0;
+}
+static inline ssize_t read_msg(handle_t, uint32_t, uint32_t, ipc_msg_t*) {
+ return 0;
+}
+static inline int put_msg(handle_t, uint32_t) {
+ return 0;
+}
+static inline ssize_t send_msg(handle_t, ipc_msg_t*) {
+ return 0;
+}
diff --git a/libs/binder/trusty/include_mock/trusty_log.h b/libs/binder/trusty/include_mock/trusty_log.h
new file mode 100644
index 0000000..d51e752
--- /dev/null
+++ b/libs/binder/trusty/include_mock/trusty_log.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 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
+
+#include <stdio.h>
+
+// Mock definitions for the Trusty logging macros. These are not
+// meant to be run, just compiled successfully.
+#define TLOGD(fmt, ...) printf(fmt, ##__VA_ARGS__)
+#define TLOGI(fmt, ...) printf(fmt, ##__VA_ARGS__)
+#define TLOGW(fmt, ...) printf(fmt, ##__VA_ARGS__)
+#define TLOGE(fmt, ...) printf(fmt, ##__VA_ARGS__)
+#define TLOGC(fmt, ...) printf(fmt, ##__VA_ARGS__)
diff --git a/libs/binder/trusty/include_mock/uapi/err.h b/libs/binder/trusty/include_mock/uapi/err.h
new file mode 100644
index 0000000..c7e117e
--- /dev/null
+++ b/libs/binder/trusty/include_mock/uapi/err.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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
+
+enum {
+ NO_ERROR,
+ ERR_ACCESS_DENIED,
+ ERR_ALREADY_EXISTS,
+ ERR_BAD_HANDLE,
+ ERR_BAD_LEN,
+ ERR_BAD_STATE,
+ ERR_CHANNEL_CLOSED,
+ ERR_CMD_UNKNOWN,
+ ERR_GENERIC,
+ ERR_INVALID_ARGS,
+ ERR_NO_MEMORY,
+ ERR_NO_MSG,
+ ERR_NOT_ALLOWED,
+ ERR_NOT_CONFIGURED,
+ ERR_NOT_ENOUGH_BUFFER,
+ ERR_NOT_FOUND,
+ ERR_NOT_READY,
+ ERR_NOT_SUPPORTED,
+ ERR_NOT_VALID,
+ ERR_TIMED_OUT,
+ ERR_TOO_BIG,
+};
diff --git a/libs/binder/trusty/include_mock/uapi/trusty_uuid.h b/libs/binder/trusty/include_mock/uapi/trusty_uuid.h
new file mode 100644
index 0000000..f636826
--- /dev/null
+++ b/libs/binder/trusty/include_mock/uapi/trusty_uuid.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 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
+
+typedef struct uuid {
+ int placeholder;
+} uuid_t;
diff --git a/libs/binder/trusty/logging.cpp b/libs/binder/trusty/logging.cpp
index fd54744..b4243af 100644
--- a/libs/binder/trusty/logging.cpp
+++ b/libs/binder/trusty/logging.cpp
@@ -54,7 +54,7 @@
abort();
}
-static void TrustyLogLine(const char* msg, int length, android::base::LogSeverity severity,
+static void TrustyLogLine(const char* msg, int /*length*/, android::base::LogSeverity severity,
const char* tag) {
switch (severity) {
case VERBOSE:
@@ -157,7 +157,7 @@
TrustyLogger(DEFAULT, severity, tag ?: "<unknown>", file, line, message);
}
-bool ShouldLog(LogSeverity severity, const char* tag) {
+bool ShouldLog(LogSeverity /*severity*/, const char* /*tag*/) {
// This is controlled by Trusty's log level.
return true;
}
diff --git a/libs/binder/trusty/rules.mk b/libs/binder/trusty/rules.mk
index 83475f5..4e5cd18 100644
--- a/libs/binder/trusty/rules.mk
+++ b/libs/binder/trusty/rules.mk
@@ -36,6 +36,7 @@
$(LIBBINDER_DIR)/IInterface.cpp \
$(LIBBINDER_DIR)/IResultReceiver.cpp \
$(LIBBINDER_DIR)/Parcel.cpp \
+ $(LIBBINDER_DIR)/ParcelFileDescriptor.cpp \
$(LIBBINDER_DIR)/RpcServer.cpp \
$(LIBBINDER_DIR)/RpcSession.cpp \
$(LIBBINDER_DIR)/RpcState.cpp \
@@ -75,7 +76,6 @@
$(LIBBINDER_DIR)/ndk/include_cpp \
MODULE_EXPORT_COMPILEFLAGS += \
- -DBINDER_NO_KERNEL_IPC \
-DBINDER_RPC_SINGLE_THREADED \
-D__ANDROID_VNDK__ \
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
index 44e2fd1..2f73137 100644
--- a/libs/binderthreadstate/test.cpp
+++ b/libs/binderthreadstate/test.cpp
@@ -68,8 +68,13 @@
static void callAidl(size_t id, int32_t idx) {
sp<IAidlStuff> stuff;
- CHECK(OK == android::getService<IAidlStuff>(String16(id2name(id).c_str()), &stuff));
- CHECK(stuff->call(idx).isOk());
+ CHECK_EQ(OK, android::getService<IAidlStuff>(String16(id2name(id).c_str()), &stuff));
+ auto ret = stuff->call(idx);
+ CHECK(ret.isOk()) << ret;
+}
+
+static inline std::ostream& operator<<(std::ostream& o, const BinderCallType& s) {
+ return o << static_cast<std::underlying_type_t<BinderCallType>>(s);
}
class HidlServer : public IHidlStuff {
@@ -79,13 +84,13 @@
size_t otherId;
Return<void> callLocal() {
- CHECK(BinderCallType::NONE == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::NONE, getCurrentServingCall());
return android::hardware::Status::ok();
}
Return<void> call(int32_t idx) {
LOG(INFO) << "HidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
<< " with tid: " << gettid();
- CHECK(BinderCallType::HWBINDER == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
if (idx > 0) {
if (thisId == kP1Id && idx % 4 < 2) {
callHidl(otherId, idx - 1);
@@ -93,7 +98,7 @@
callAidl(otherId, idx - 1);
}
}
- CHECK(BinderCallType::HWBINDER == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
return android::hardware::Status::ok();
}
};
@@ -104,13 +109,13 @@
size_t otherId;
Status callLocal() {
- CHECK(BinderCallType::NONE == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::NONE, getCurrentServingCall());
return Status::ok();
}
Status call(int32_t idx) {
LOG(INFO) << "AidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
<< " with tid: " << gettid();
- CHECK(BinderCallType::BINDER == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
if (idx > 0) {
if (thisId == kP2Id && idx % 4 < 2) {
callHidl(otherId, idx - 1);
@@ -118,7 +123,7 @@
callAidl(otherId, idx - 1);
}
}
- CHECK(BinderCallType::BINDER == getCurrentServingCall());
+ CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
return Status::ok();
}
};
@@ -161,13 +166,14 @@
// AIDL
android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
sp<AidlServer> aidlServer = new AidlServer(thisId, otherId);
- CHECK(OK == defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer));
+ CHECK_EQ(OK,
+ defaultServiceManager()->addService(String16(id2name(thisId).c_str()), aidlServer));
android::ProcessState::self()->startThreadPool();
// HIDL
android::hardware::configureRpcThreadpool(1, true /*callerWillJoin*/);
sp<IHidlStuff> hidlServer = new HidlServer(thisId, otherId);
- CHECK(OK == hidlServer->registerAsService(id2name(thisId).c_str()));
+ CHECK_EQ(OK, hidlServer->registerAsService(id2name(thisId).c_str()));
android::hardware::joinRpcThreadpool();
return EXIT_FAILURE;
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
index 31bf895..05b5533 100644
--- a/libs/gui/OWNERS
+++ b/libs/gui/OWNERS
@@ -2,8 +2,9 @@
alecmouri@google.com
chaviw@google.com
chrisforbes@google.com
-lpy@google.com
jreck@google.com
+lpy@google.com
+pdwilliams@google.com
racarr@google.com
vishnun@google.com
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index 59cc7d1..d6b4579 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -25,8 +25,10 @@
#include <utils/Errors.h>
#include <utils/Timers.h>
#include <utils/Tokenizer.h>
+#if defined(__ANDROID__)
#include <vintf/RuntimeInfo.h>
#include <vintf/VintfObject.h>
+#endif
#include <cstdlib>
#include <string_view>
@@ -79,6 +81,7 @@
sensorPair<InputDeviceSensorType::SIGNIFICANT_MOTION>()};
bool kernelConfigsArePresent(const std::set<std::string>& configs) {
+#if defined(__ANDROID__)
std::shared_ptr<const android::vintf::RuntimeInfo> runtimeInfo =
android::vintf::VintfObject::GetInstance()->getRuntimeInfo(
vintf::RuntimeInfo::FetchFlag::CONFIG_GZ);
@@ -99,6 +102,10 @@
}
}
return true;
+#else
+ (void)configs; // Suppress 'unused variable' warning
+ return true;
+#endif
}
} // namespace
diff --git a/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp b/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp
index 129f430..0e110b7 100644
--- a/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp
+++ b/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp
@@ -26,8 +26,10 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fdp(data, size);
struct sensor_t sensor_type;
- sensor_type.name = fdp.ConsumeBytesAsString(MAX_STR_LEN).c_str();
- sensor_type.vendor = fdp.ConsumeBytesAsString(MAX_STR_LEN).c_str();
+ std::string name = fdp.ConsumeBytesAsString(MAX_STR_LEN);
+ sensor_type.name = name.c_str();
+ std::string vendor = fdp.ConsumeBytesAsString(MAX_STR_LEN);
+ sensor_type.vendor = vendor.c_str();
sensor_type.stringType = "";
sensor_type.requiredPermission = "";
sensor_type.version = fdp.ConsumeIntegral<int>();
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index 2ece51c..6011d0d 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -2,6 +2,7 @@
alecmouri@google.com
chaviw@google.com
lpy@google.com
+pdwilliams@google.com
racarr@google.com
scroggo@google.com
-vishnun@google.com
\ No newline at end of file
+vishnun@google.com
diff --git a/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp b/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp
index fb4458a..9162674 100644
--- a/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp
+++ b/services/surfaceflinger/tests/RefreshRateOverlay_test.cpp
@@ -80,14 +80,6 @@
} // namespace
-TEST(RefreshRateOverlayTest, enableOverlay) {
- toggleOverlay(true);
-}
-
-TEST(RefreshRateOverlayTest, disableOverlay) {
- toggleOverlay(false);
-}
-
TEST(RefreshRateOverlayTest, enableAndDisableOverlay) {
toggleOverlay(true);
toggleOverlay(false);
diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp
index 2002bdf..5403baf 100644
--- a/services/vibratorservice/Android.bp
+++ b/services/vibratorservice/Android.bp
@@ -59,6 +59,12 @@
"-Wunreachable-code",
],
+ // FIXME: Workaround LTO build breakage
+ // http://b/241699694
+ lto: {
+ never: true,
+ },
+
local_include_dirs: ["include"],
export_include_dirs: ["include"],