Merge "Add bindgen bindings test"
diff --git a/cmds/cmd/fuzzer/Android.bp b/cmds/cmd/fuzzer/Android.bp
index 8262bc2..a65f6de 100644
--- a/cmds/cmd/fuzzer/Android.bp
+++ b/cmds/cmd/fuzzer/Android.bp
@@ -30,12 +30,12 @@
],
static_libs: [
"libcmd",
- "libutils",
"liblog",
"libselinux",
],
shared_libs: [
"libbinder",
+ "libutils",
],
fuzz_config: {
cc: [
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 99e0f4c..b2da6d5 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -24,7 +24,7 @@
cc_defaults {
name: "idlcli-defaults",
shared_libs: [
- "android.hardware.vibrator-V1-ndk_platform",
+ "android.hardware.vibrator-V1-ndk",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 72d8afd..9875079 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -271,6 +271,15 @@
defaults: ["libbinder_tls_defaults"],
}
+// For testing
+cc_library_static {
+ name: "libbinder_tls_static",
+ defaults: ["libbinder_tls_defaults"],
+ visibility: [
+ ":__subpackages__",
+ ],
+}
+
// AIDL interface between libbinder and framework.jar
filegroup {
name: "libbinder_aidl",
@@ -289,6 +298,9 @@
"aidl/android/content/pm/IPackageChangeObserver.aidl",
"aidl/android/content/pm/IPackageManagerNative.aidl",
"aidl/android/content/pm/PackageChangeEvent.aidl",
+ "aidl/android/content/pm/IStagedApexObserver.aidl",
+ "aidl/android/content/pm/ApexStagedEvent.aidl",
+ "aidl/android/content/pm/StagedApexInfo.aidl",
],
path: "aidl",
}
@@ -329,6 +341,8 @@
"//packages/modules/Virtualization/authfs:__subpackages__",
"//packages/modules/Virtualization/compos:__subpackages__",
"//packages/modules/Virtualization/microdroid",
+ "//packages/modules/Virtualization/microdroid_manager",
+ "//packages/modules/Virtualization/virtualizationservice",
],
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 956524a..b545484 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -104,7 +104,7 @@
switch (obj.hdr.type) {
case BINDER_TYPE_BINDER:
if (obj.binder) {
- LOG_REFS("Parcel %p acquiring reference on local %p", who, obj.cookie);
+ LOG_REFS("Parcel %p acquiring reference on local %llu", who, obj.cookie);
reinterpret_cast<IBinder*>(obj.cookie)->incStrong(who);
}
return;
@@ -137,7 +137,7 @@
switch (obj.hdr.type) {
case BINDER_TYPE_BINDER:
if (obj.binder) {
- LOG_REFS("Parcel %p releasing reference on local %p", who, obj.cookie);
+ LOG_REFS("Parcel %p releasing reference on local %llu", who, obj.cookie);
reinterpret_cast<IBinder*>(obj.cookie)->decStrong(who);
}
return;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index caa00a5..15b8604 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -18,6 +18,7 @@
#include <binder/ProcessState.h>
+#include <android-base/result.h>
#include <binder/BpBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -384,74 +385,78 @@
return mDriverName;
}
-static int open_driver(const char *driver)
-{
+static base::Result<int> open_driver(const char* driver) {
int fd = open(driver, O_RDWR | O_CLOEXEC);
- if (fd >= 0) {
- int vers = 0;
- status_t result = ioctl(fd, BINDER_VERSION, &vers);
- if (result == -1) {
- ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
- close(fd);
- fd = -1;
- }
- if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
- ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
- vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
- close(fd);
- fd = -1;
- }
- size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
- result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
- if (result == -1) {
- ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
- }
- uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
- result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
- if (result == -1) {
- ALOGV("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
- }
- } else {
- ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
+ if (fd < 0) {
+ return base::ErrnoError() << "Opening '" << driver << "' failed";
+ }
+ int vers = 0;
+ status_t result = ioctl(fd, BINDER_VERSION, &vers);
+ if (result == -1) {
+ close(fd);
+ return base::ErrnoError() << "Binder ioctl to obtain version failed";
+ }
+ if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
+ close(fd);
+ return base::Error() << "Binder driver protocol(" << vers
+ << ") does not match user space protocol("
+ << BINDER_CURRENT_PROTOCOL_VERSION
+ << ")! ioctl() return value: " << result;
+ }
+ size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
+ result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
+ if (result == -1) {
+ ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
+ }
+ uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
+ result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
+ if (result == -1) {
+ ALOGV("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
}
return fd;
}
-ProcessState::ProcessState(const char *driver)
- : mDriverName(String8(driver))
- , mDriverFD(open_driver(driver))
- , mVMStart(MAP_FAILED)
- , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
- , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
- , mExecutingThreadsCount(0)
- , mWaitingForThreads(0)
- , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
- , mStarvationStartTimeMs(0)
- , mThreadPoolStarted(false)
- , mThreadPoolSeq(1)
- , mCallRestriction(CallRestriction::NONE)
-{
-
+ProcessState::ProcessState(const char* driver)
+ : mDriverName(String8(driver)),
+ mDriverFD(-1),
+ mVMStart(MAP_FAILED),
+ mThreadCountLock(PTHREAD_MUTEX_INITIALIZER),
+ mThreadCountDecrement(PTHREAD_COND_INITIALIZER),
+ mExecutingThreadsCount(0),
+ mWaitingForThreads(0),
+ mMaxThreads(DEFAULT_MAX_BINDER_THREADS),
+ mStarvationStartTimeMs(0),
+ mThreadPoolStarted(false),
+ mThreadPoolSeq(1),
+ mCallRestriction(CallRestriction::NONE) {
// TODO(b/166468760): enforce in build system
#if defined(__ANDROID_APEX__)
LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.");
#endif
- if (mDriverFD >= 0) {
+ base::Result<int> opened = open_driver(driver);
+
+ if (opened.ok()) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
- mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
+ mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
+ opened.value(), 0);
if (mVMStart == MAP_FAILED) {
+ close(opened.value());
// *sigh*
- ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
- close(mDriverFD);
- mDriverFD = -1;
+ opened = base::Error()
+ << "Using " << driver << " failed: unable to mmap transaction memory.";
mDriverName.clear();
}
}
#ifdef __ANDROID__
- LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened. Terminating.", driver);
+ LOG_ALWAYS_FATAL_IF(!opened.ok(), "Binder driver '%s' could not be opened. Terminating: %s",
+ driver, opened.error().message().c_str());
#endif
+
+ if (opened.ok()) {
+ mDriverFD = opened.value();
+ }
}
ProcessState::~ProcessState()
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index a20445b..ad9ba96 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -39,8 +39,7 @@
using base::ScopeGuard;
using base::unique_fd;
-RpcServer::RpcServer(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory)
- : mRpcTransportCtxFactory(std::move(rpcTransportCtxFactory)) {}
+RpcServer::RpcServer(std::unique_ptr<RpcTransportCtx> ctx) : mCtx(std::move(ctx)) {}
RpcServer::~RpcServer() {
(void)shutdown();
}
@@ -49,7 +48,9 @@
// Default is without TLS.
if (rpcTransportCtxFactory == nullptr)
rpcTransportCtxFactory = RpcTransportCtxFactoryRaw::make();
- return sp<RpcServer>::make(std::move(rpcTransportCtxFactory));
+ auto ctx = rpcTransportCtxFactory->newServerCtx();
+ if (ctx == nullptr) return nullptr;
+ return sp<RpcServer>::make(std::move(ctx));
}
void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() {
@@ -138,6 +139,20 @@
return ret;
}
+std::string RpcServer::getCertificate(CertificateFormat format) {
+ std::lock_guard<std::mutex> _l(mLock);
+ return mCtx->getCertificate(format);
+}
+
+status_t RpcServer::addTrustedPeerCertificate(CertificateFormat format, std::string_view cert) {
+ std::lock_guard<std::mutex> _l(mLock);
+ // Ensure that join thread is not running or shutdown trigger is not set up. In either case,
+ // it means there are child threads running. It is invalid to add trusted peer certificates
+ // after join thread and/or child threads are running to avoid race condition.
+ if (mJoinThreadRunning || mShutdownTrigger != nullptr) return INVALID_OPERATION;
+ return mCtx->addTrustedPeerCertificate(format, cert);
+}
+
static void joinRpcServer(sp<RpcServer>&& thiz) {
thiz->join();
}
@@ -159,10 +174,6 @@
mJoinThreadRunning = true;
mShutdownTrigger = FdTrigger::make();
LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr, "Cannot create join signaler");
-
- mCtx = mRpcTransportCtxFactory->newServerCtx();
- LOG_ALWAYS_FATAL_IF(mCtx == nullptr, "Unable to create RpcTransportCtx with %s sockets",
- mRpcTransportCtxFactory->toCString());
}
status_t status;
@@ -229,7 +240,6 @@
LOG_RPC_DETAIL("Finished waiting on shutdown.");
mShutdownTrigger = nullptr;
- mCtx = nullptr;
return true;
}
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 4c47005..c57b749 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -49,8 +49,7 @@
using base::unique_fd;
-RpcSession::RpcSession(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory)
- : mRpcTransportCtxFactory(std::move(rpcTransportCtxFactory)) {
+RpcSession::RpcSession(std::unique_ptr<RpcTransportCtx> ctx) : mCtx(std::move(ctx)) {
LOG_RPC_DETAIL("RpcSession created %p", this);
mState = std::make_unique<RpcState>();
@@ -63,11 +62,26 @@
"Should not be able to destroy a session with servers in use.");
}
-sp<RpcSession> RpcSession::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) {
+sp<RpcSession> RpcSession::make() {
// Default is without TLS.
- if (rpcTransportCtxFactory == nullptr)
- rpcTransportCtxFactory = RpcTransportCtxFactoryRaw::make();
- return sp<RpcSession>::make(std::move(rpcTransportCtxFactory));
+ return make(RpcTransportCtxFactoryRaw::make(), std::nullopt, std::nullopt);
+}
+
+sp<RpcSession> RpcSession::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory,
+ std::optional<CertificateFormat> serverCertificateFormat,
+ std::optional<std::string> serverCertificate) {
+ auto ctx = rpcTransportCtxFactory->newClientCtx();
+ if (ctx == nullptr) return nullptr;
+ LOG_ALWAYS_FATAL_IF(serverCertificateFormat.has_value() != serverCertificate.has_value());
+ if (serverCertificateFormat.has_value() && serverCertificate.has_value()) {
+ status_t status =
+ ctx->addTrustedPeerCertificate(*serverCertificateFormat, *serverCertificate);
+ if (status != OK) {
+ ALOGE("Cannot add trusted server certificate: %s", statusToString(status).c_str());
+ return nullptr;
+ }
+ }
+ return sp<RpcSession>::make(std::move(ctx));
}
void RpcSession::setMaxThreads(size_t threads) {
@@ -155,12 +169,7 @@
return -savedErrno;
}
- auto ctx = mRpcTransportCtxFactory->newClientCtx();
- if (ctx == nullptr) {
- ALOGE("Unable to create RpcTransportCtx for null debugging client");
- return NO_MEMORY;
- }
- auto server = ctx->newTransport(std::move(serverFd), mShutdownTrigger.get());
+ auto server = mCtx->newTransport(std::move(serverFd), mShutdownTrigger.get());
if (server == nullptr) {
ALOGE("Unable to set up RpcTransport");
return UNKNOWN_ERROR;
@@ -484,37 +493,39 @@
}
if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
- if (errno == ECONNRESET) {
+ 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);
+ if (pollStatus != OK) {
+ ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
+ statusToString(pollStatus).c_str());
+ return pollStatus;
+ }
+ // 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);
+ if (ret == -1) {
+ int savedErrno = errno;
+ ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s. "
+ "(Original error from connect() is: %s)",
+ strerror(savedErrno), strerror(connErrno));
+ return -savedErrno;
+ }
+ // Retrieved the real connErrno as if connect() was called with a blocking socket
+ // fd. Continue checking connErrno.
+ }
+ if (connErrno == ECONNRESET) {
ALOGW("Connection reset on %s", addr.toString().c_str());
continue;
}
- if (errno != EAGAIN && errno != EINPROGRESS) {
- int savedErrno = errno;
+ // connErrno could be zero if getsockopt determines so. Hence zero-check again.
+ if (connErrno != 0) {
ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
- strerror(savedErrno));
- return -savedErrno;
- }
- // 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);
- if (pollStatus != OK) {
- ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
- statusToString(pollStatus).c_str());
- return pollStatus;
- }
- int soError;
- socklen_t soErrorLen = sizeof(soError);
- int ret = getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &soError, &soErrorLen);
- if (ret == -1) {
- int savedErrno = errno;
- ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s",
- strerror(savedErrno));
- return -savedErrno;
- }
- if (soError != 0) {
- ALOGE("After connect(), getsockopt() returns error for socket at %s: %s",
- addr.toString().c_str(), strerror(soError));
- return -soError;
+ strerror(connErrno));
+ return -connErrno;
}
}
LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
@@ -529,15 +540,9 @@
status_t RpcSession::initAndAddConnection(unique_fd fd, const RpcAddress& sessionId,
bool incoming) {
LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr);
- auto ctx = mRpcTransportCtxFactory->newClientCtx();
- if (ctx == nullptr) {
- ALOGE("Unable to create client RpcTransportCtx with %s sockets",
- mRpcTransportCtxFactory->toCString());
- return NO_MEMORY;
- }
- auto server = ctx->newTransport(std::move(fd), mShutdownTrigger.get());
+ auto server = mCtx->newTransport(std::move(fd), mShutdownTrigger.get());
if (server == nullptr) {
- ALOGE("Unable to set up RpcTransport in %s context", mRpcTransportCtxFactory->toCString());
+ ALOGE("%s: Unable to set up RpcTransport", __PRETTY_FUNCTION__);
return UNKNOWN_ERROR;
}
@@ -692,6 +697,10 @@
return false;
}
+std::string RpcSession::getCertificate(CertificateFormat format) {
+ return mCtx->getCertificate(format);
+}
+
status_t RpcSession::ExclusiveConnection::find(const sp<RpcSession>& session, ConnectionUse use,
ExclusiveConnection* connection) {
connection->mSession = session;
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index d77fc52..930df12 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -111,7 +111,10 @@
std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, FdTrigger*) const {
return std::make_unique<RpcTransportRaw>(std::move(fd));
}
+ std::string getCertificate(CertificateFormat) const override { return {}; }
+ status_t addTrustedPeerCertificate(CertificateFormat, std::string_view) override { return OK; }
};
+
} // namespace
std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryRaw::newServerCtx() const {
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
index a102913..e6cb04e 100644
--- a/libs/binder/RpcTransportTls.cpp
+++ b/libs/binder/RpcTransportTls.cpp
@@ -166,6 +166,34 @@
}
}
+// Helper class to ErrorQueue::toString
+class ErrorQueueString {
+public:
+ static std::string toString() {
+ ErrorQueueString thiz;
+ ERR_print_errors_cb(staticCallback, &thiz);
+ return thiz.mSs.str();
+ }
+
+private:
+ static int staticCallback(const char* str, size_t len, void* ctx) {
+ return reinterpret_cast<ErrorQueueString*>(ctx)->callback(str, len);
+ }
+ int callback(const char* str, size_t len) {
+ if (len == 0) return 1; // continue
+ // ERR_print_errors_cb place a new line at the end, but it doesn't say so in the API.
+ if (str[len - 1] == '\n') len -= 1;
+ if (!mIsFirst) {
+ mSs << '\n';
+ }
+ mSs << std::string_view(str, len);
+ mIsFirst = false;
+ return 1; // continue
+ }
+ std::stringstream mSs;
+ bool mIsFirst = true;
+};
+
// Handles libssl's error queue.
//
// Call into any of its member functions to ensure the error queue is properly handled or cleared.
@@ -182,17 +210,10 @@
// Stores the error queue in |ssl| into a string, then clears the error queue.
std::string toString() {
- std::stringstream ss;
- ERR_print_errors_cb(
- [](const char* str, size_t len, void* ctx) {
- auto ss = (std::stringstream*)ctx;
- (*ss) << std::string_view(str, len) << "\n";
- return 1; // continue
- },
- &ss);
+ auto ret = ErrorQueueString::toString();
// Though ERR_print_errors_cb should have cleared it, it is okay to clear again.
clear();
- return ss.str();
+ return ret;
}
// |sslError| should be from Ssl::getError().
@@ -428,65 +449,46 @@
}
}
-class RpcTransportCtxTlsServer : public RpcTransportCtx {
+class RpcTransportCtxTls : public RpcTransportCtx {
public:
- static std::unique_ptr<RpcTransportCtxTlsServer> create();
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd acceptedFd,
+ template <typename Impl,
+ typename = std::enable_if_t<std::is_base_of_v<RpcTransportCtxTls, Impl>>>
+ static std::unique_ptr<RpcTransportCtxTls> create();
+ std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
FdTrigger* fdTrigger) const override;
+ std::string getCertificate(CertificateFormat) const override;
+ status_t addTrustedPeerCertificate(CertificateFormat, std::string_view cert) override;
-private:
+protected:
+ virtual void preHandshake(Ssl* ssl) const = 0;
bssl::UniquePtr<SSL_CTX> mCtx;
};
-std::unique_ptr<RpcTransportCtxTlsServer> RpcTransportCtxTlsServer::create() {
+std::string RpcTransportCtxTls::getCertificate(CertificateFormat) const {
+ // TODO(b/195166979): return certificate here
+ return {};
+}
+
+status_t RpcTransportCtxTls::addTrustedPeerCertificate(CertificateFormat, std::string_view) {
+ // TODO(b/195166979): set certificate here
+ return OK;
+}
+
+// Common implementation for creating server and client contexts. The child class, |Impl|, is
+// provided as a template argument so that this function can initialize an |Impl| object.
+template <typename Impl, typename>
+std::unique_ptr<RpcTransportCtxTls> RpcTransportCtxTls::create() {
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
TEST_AND_RETURN(nullptr, ctx != nullptr);
- // Server use self-signing cert
auto evp_pkey = makeKeyPairForSelfSignedCert();
TEST_AND_RETURN(nullptr, evp_pkey != nullptr);
auto cert = makeSelfSignedCert(evp_pkey.get(), kCertValidDays);
TEST_AND_RETURN(nullptr, cert != nullptr);
TEST_AND_RETURN(nullptr, SSL_CTX_use_PrivateKey(ctx.get(), evp_pkey.get()));
TEST_AND_RETURN(nullptr, SSL_CTX_use_certificate(ctx.get(), cert.get()));
- // Require at least TLS 1.3
- TEST_AND_RETURN(nullptr, SSL_CTX_set_min_proto_version(ctx.get(), TLS1_3_VERSION));
- if constexpr (SHOULD_LOG_TLS_DETAIL) { // NOLINT
- SSL_CTX_set_info_callback(ctx.get(), sslDebugLog);
- }
-
- auto rpcTransportTlsServerCtx = std::make_unique<RpcTransportCtxTlsServer>();
- rpcTransportTlsServerCtx->mCtx = std::move(ctx);
- return rpcTransportTlsServerCtx;
-}
-
-std::unique_ptr<RpcTransport> RpcTransportCtxTlsServer::newTransport(
- android::base::unique_fd acceptedFd, FdTrigger* fdTrigger) const {
- bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get()));
- TEST_AND_RETURN(nullptr, ssl != nullptr);
- Ssl wrapped(std::move(ssl));
-
- wrapped.call(SSL_set_accept_state).errorQueue.clear();
- TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, acceptedFd, fdTrigger));
- return std::make_unique<RpcTransportTls>(std::move(acceptedFd), std::move(wrapped));
-}
-
-class RpcTransportCtxTlsClient : public RpcTransportCtx {
-public:
- static std::unique_ptr<RpcTransportCtxTlsClient> create();
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd connectedFd,
- FdTrigger* fdTrigger) const override;
-
-private:
- bssl::UniquePtr<SSL_CTX> mCtx;
-};
-
-std::unique_ptr<RpcTransportCtxTlsClient> RpcTransportCtxTlsClient::create() {
- bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
- TEST_AND_RETURN(nullptr, ctx != nullptr);
-
- // TODO(b/195166979): server should send certificate in a different channel, and client
+ // TODO(b/195166979): peer should send certificate in a different channel, and this class
// should verify it here.
SSL_CTX_set_custom_verify(ctx.get(), SSL_VERIFY_PEER,
[](SSL*, uint8_t*) -> ssl_verify_result_t { return ssl_verify_ok; });
@@ -498,30 +500,44 @@
SSL_CTX_set_info_callback(ctx.get(), sslDebugLog);
}
- auto rpcTransportTlsClientCtx = std::make_unique<RpcTransportCtxTlsClient>();
- rpcTransportTlsClientCtx->mCtx = std::move(ctx);
- return rpcTransportTlsClientCtx;
+ auto ret = std::make_unique<Impl>();
+ ret->mCtx = std::move(ctx);
+ return ret;
}
-std::unique_ptr<RpcTransport> RpcTransportCtxTlsClient::newTransport(
- android::base::unique_fd connectedFd, FdTrigger* fdTrigger) const {
+std::unique_ptr<RpcTransport> RpcTransportCtxTls::newTransport(android::base::unique_fd fd,
+ FdTrigger* fdTrigger) const {
bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get()));
TEST_AND_RETURN(nullptr, ssl != nullptr);
Ssl wrapped(std::move(ssl));
- wrapped.call(SSL_set_connect_state).errorQueue.clear();
- TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, connectedFd, fdTrigger));
- return std::make_unique<RpcTransportTls>(std::move(connectedFd), std::move(wrapped));
+ preHandshake(&wrapped);
+ TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, fd, fdTrigger));
+ return std::make_unique<RpcTransportTls>(std::move(fd), std::move(wrapped));
}
+class RpcTransportCtxTlsServer : public RpcTransportCtxTls {
+protected:
+ void preHandshake(Ssl* ssl) const override {
+ ssl->call(SSL_set_accept_state).errorQueue.clear();
+ }
+};
+
+class RpcTransportCtxTlsClient : public RpcTransportCtxTls {
+protected:
+ void preHandshake(Ssl* ssl) const override {
+ ssl->call(SSL_set_connect_state).errorQueue.clear();
+ }
+};
+
} // namespace
std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newServerCtx() const {
- return android::RpcTransportCtxTlsServer::create();
+ return android::RpcTransportCtxTls::create<RpcTransportCtxTlsServer>();
}
std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newClientCtx() const {
- return android::RpcTransportCtxTlsClient::create();
+ return android::RpcTransportCtxTls::create<RpcTransportCtxTlsClient>();
}
const char* RpcTransportCtxFactoryTls::toCString() const {
diff --git a/libs/binder/RpcWireFormat.h b/libs/binder/RpcWireFormat.h
index 0f8efd2..c73d8c2 100644
--- a/libs/binder/RpcWireFormat.h
+++ b/libs/binder/RpcWireFormat.h
@@ -115,12 +115,12 @@
uint32_t reserved[4];
- uint8_t data[0];
+ uint8_t data[];
};
struct RpcWireReply {
int32_t status; // transact return
- uint8_t data[0];
+ uint8_t data[];
};
#pragma clang diagnostic pop
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 9c5ce67..ebb0d27 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -34,6 +34,9 @@
"name": "binderStabilityTest"
},
{
+ "name": "binderRpcWireProtocolTest"
+ },
+ {
"name": "binderUtilsHostTest"
},
{
diff --git a/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl b/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl
new file mode 100644
index 0000000..75f8753
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package android.content.pm;
+
+/**
+ * This event is designed for notification to native code listener about
+ * any changes to set of apex packages staged for installation on next boot.
+ *
+ * @hide
+ */
+parcelable ApexStagedEvent {
+ @utf8InCpp String[] stagedApexModuleNames;
+}
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index dc8d74c..c076be7 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -18,6 +18,8 @@
package android.content.pm;
import android.content.pm.IPackageChangeObserver;
+import android.content.pm.IStagedApexObserver;
+import android.content.pm.StagedApexInfo;
/**
* Parallel implementation of certain {@link PackageManager} APIs that need to
@@ -101,4 +103,24 @@
* This does nothing if this observer was not already registered.
*/
void unregisterPackageChangeObserver(in IPackageChangeObserver observer);
+
+ /** Register a observer for change in set of staged APEX ready for installation */
+ void registerStagedApexObserver(in IStagedApexObserver observer);
+
+ /**
+ * Unregister an existing staged apex observer.
+ * This does nothing if this observer was not already registered.
+ */
+ void unregisterStagedApexObserver(in IStagedApexObserver observer);
+
+ /**
+ * Get APEX module names of all APEX that are staged ready for installation
+ */
+ @utf8InCpp String[] getStagedApexModuleNames();
+
+ /**
+ * Get information of APEX which is staged ready for installation.
+ * Returns null if no such APEX is found.
+ */
+ StagedApexInfo getStagedApexInfo(in @utf8InCpp String moduleName);
}
diff --git a/libs/binder/aidl/android/content/pm/IStagedApexObserver.aidl b/libs/binder/aidl/android/content/pm/IStagedApexObserver.aidl
new file mode 100644
index 0000000..9906436
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/IStagedApexObserver.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package android.content.pm;
+
+import android.content.pm.ApexStagedEvent;
+
+/**
+ * This is a non-blocking notification when set of staged apex has changed
+ *
+ * @hide
+ */
+oneway interface IStagedApexObserver {
+ void onApexStaged(in ApexStagedEvent event);
+}
diff --git a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
new file mode 100644
index 0000000..ece7989
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package android.content.pm;
+
+/**
+ * This object is designed for returning information regarding
+ * staged APEX that are ready to be installed on next reboot.
+ *
+ * @hide
+ */
+parcelable StagedApexInfo {
+ @utf8InCpp String moduleName;
+ @utf8InCpp String diskImagePath;
+ long versionCode;
+ @utf8InCpp String versionName;
+}
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index bf3e7e0..d0e4e27 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -134,6 +134,17 @@
sp<IBinder> getRootObject();
/**
+ * See RpcTransportCtx::getCertificate
+ */
+ std::string getCertificate(CertificateFormat);
+
+ /**
+ * See RpcTransportCtx::addTrustedPeerCertificate.
+ * Thread-safe. This is only possible before the server is join()-ing.
+ */
+ status_t addTrustedPeerCertificate(CertificateFormat, std::string_view cert);
+
+ /**
* Runs join() in a background thread. Immediately returns.
*/
void start();
@@ -170,7 +181,7 @@
private:
friend sp<RpcServer>;
- explicit RpcServer(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory);
+ explicit RpcServer(std::unique_ptr<RpcTransportCtx> ctx);
void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override;
void onSessionIncomingThreadEnded() override;
@@ -178,7 +189,7 @@
static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd);
status_t setupSocketServer(const RpcSocketAddress& address);
- const std::unique_ptr<RpcTransportCtxFactory> mRpcTransportCtxFactory;
+ const std::unique_ptr<RpcTransportCtx> mCtx;
bool mAgreedExperimental = false;
size_t mMaxThreads = 1;
std::optional<uint32_t> mProtocolVersion;
@@ -193,7 +204,6 @@
std::map<RpcAddress, sp<RpcSession>> mSessions;
std::unique_ptr<FdTrigger> mShutdownTrigger;
std::condition_variable mShutdownCv;
- std::unique_ptr<RpcTransportCtx> mCtx;
};
} // namespace android
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 6e6eb74..d92af0a 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -51,8 +51,15 @@
*/
class RpcSession final : public virtual RefBase {
public:
- static sp<RpcSession> make(
- std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr);
+ // Create an RpcSession with default configuration (raw sockets).
+ static sp<RpcSession> make();
+
+ // Create an RpcSession with the given configuration. |serverCertificateFormat| and
+ // |serverCertificate| must have values or be nullopt simultaneously. If they have values, set
+ // server certificate.
+ static sp<RpcSession> make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory,
+ std::optional<CertificateFormat> serverCertificateFormat,
+ std::optional<std::string> serverCertificate);
/**
* Set the maximum number of threads allowed to be made (for things like callbacks).
@@ -125,6 +132,11 @@
status_t getRemoteMaxThreads(size_t* maxThreads);
/**
+ * See RpcTransportCtx::getCertificate
+ */
+ std::string getCertificate(CertificateFormat);
+
+ /**
* Shuts down the service.
*
* For client sessions, wait can be true or false. For server sessions,
@@ -159,7 +171,7 @@
friend sp<RpcSession>;
friend RpcServer;
friend RpcState;
- explicit RpcSession(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory);
+ explicit RpcSession(std::unique_ptr<RpcTransportCtx> ctx);
class EventListener : public virtual RefBase {
public:
@@ -259,7 +271,7 @@
bool mReentrant = false;
};
- const std::unique_ptr<RpcTransportCtxFactory> mRpcTransportCtxFactory;
+ const std::unique_ptr<RpcTransportCtx> mCtx;
// On the other side of a session, for each of mOutgoingConnections here, there should
// be one of mIncomingConnections on the other side (and vice versa).
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index 1b69519..8d08b34 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -29,7 +29,13 @@
class FdTrigger;
+enum class CertificateFormat {
+ PEM,
+ // TODO(b/195166979): support other formats, e.g. DER
+};
+
// Represents a socket connection.
+// No thread-safety is guaranteed for these APIs.
class RpcTransport {
public:
virtual ~RpcTransport() = default;
@@ -53,22 +59,43 @@
};
// Represents the context that generates the socket connection.
+// All APIs are thread-safe. See RpcTransportCtxRaw and RpcTransportCtxTls for details.
class RpcTransportCtx {
public:
virtual ~RpcTransportCtx() = default;
// Create a new RpcTransport object.
//
- // Implemenion details: for TLS, this function may incur I/O. |fdTrigger| may be used
+ // 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;
+ // Return the preconfigured certificate of this context.
+ //
+ // Implementation details:
+ // - For raw sockets, this always returns empty string.
+ // - For TLS, this returns the certificate. See RpcTransportTls for details.
+ [[nodiscard]] virtual std::string getCertificate(CertificateFormat format) const = 0;
+
+ // Add a trusted peer certificate. Peers presenting this certificate are accepted.
+ //
+ // Caller must ensure that newTransport() are called after all trusted peer certificates
+ // are added. Otherwise, RpcTransport-s created before may not trust peer certificates
+ // added later.
+ //
+ // Implementation details:
+ // - For raw sockets, this always returns OK.
+ // - For TLS, this adds trusted peer certificate. See RpcTransportTls for details.
+ [[nodiscard]] virtual status_t addTrustedPeerCertificate(CertificateFormat format,
+ std::string_view cert) = 0;
+
protected:
RpcTransportCtx() = default;
};
// A factory class that generates RpcTransportCtx.
+// All APIs are thread-safe.
class RpcTransportCtxFactory {
public:
virtual ~RpcTransportCtxFactory() = default;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 11e9fc5..23db59e 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -172,7 +172,7 @@
status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
binder_flags_t flags) {
if (isUserCommand(code)) {
- if (!data.checkInterface(this)) {
+ if (getClass()->writeHeader && !data.checkInterface(this)) {
return STATUS_BAD_TYPE;
}
@@ -354,6 +354,12 @@
clazz->onDump = onDump;
}
+void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz) {
+ CHECK(clazz != nullptr) << "disableInterfaceTokenHeader requires non-null clazz";
+
+ clazz->writeHeader = false;
+}
+
void AIBinder_Class_setHandleShellCommand(AIBinder_Class* clazz,
AIBinder_handleShellCommand handleShellCommand) {
CHECK(clazz != nullptr) << "setHandleShellCommand requires non-null clazz";
@@ -606,7 +612,10 @@
*in = new AParcel(binder);
(*in)->get()->markForBinder(binder->getBinder());
- status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
+ status_t status = android::OK;
+ if (clazz->writeHeader) {
+ status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
+ }
binder_status_t ret = PruneStatusT(status);
if (ret != STATUS_OK) {
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index f2c69b3..6509545 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -116,6 +116,9 @@
const ::android::String16& getInterfaceDescriptor() const { return mWideInterfaceDescriptor; }
const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); }
+ // whether a transaction header should be written
+ bool writeHeader = true;
+
// required to be non-null, implemented for every class
const AIBinder_Class_onCreate onCreate;
const AIBinder_Class_onDestroy onDestroy;
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 78f2d3a..c82df83 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -219,6 +219,21 @@
void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29);
/**
+ * This tells users of this class not to use a transaction header. By default, libbinder_ndk users
+ * read/write transaction headers implicitly (in the SDK, this must be manually written by
+ * android.os.Parcel#writeInterfaceToken, and it is read/checked with
+ * android.os.Parcel#enforceInterface). This method is provided in order to talk to legacy code
+ * which does not write an interface token. When this is disabled, type safety is reduced, so you
+ * must have a separate way of determining the binder you are talking to is the right type. Must
+ * be called before any instance of the class is created.
+ *
+ * Available since API level 32.
+ *
+ * \param clazz class to disable interface header on.
+ */
+void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz) __INTRODUCED_IN(32);
+
+/**
* Creates a new binder object of the appropriate class.
*
* Ownership of args is passed to this object. The lifecycle is implemented with AIBinder_incStrong
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 685ebb5..1975bdc 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -141,6 +141,11 @@
AParcel_reset;
};
+LIBBINDER_NDK32 { # introduced=32
+ global:
+ AIBinder_Class_disableInterfaceTokenHeader;
+};
+
LIBBINDER_NDK_PLATFORM {
global:
AParcel_getAllowFds;
diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp
index 488009f..8ee396e 100644
--- a/libs/binder/ndk/tests/Android.bp
+++ b/libs/binder/ndk/tests/Android.bp
@@ -71,7 +71,7 @@
srcs: ["libbinder_ndk_unit_test.cpp"],
static_libs: [
"IBinderNdkUnitTest-cpp",
- "IBinderNdkUnitTest-ndk_platform",
+ "IBinderNdkUnitTest-ndk",
],
test_suites: [
"general-tests",
@@ -88,8 +88,8 @@
],
static_libs: [
"IBinderVendorDoubleLoadTest-cpp",
- "IBinderVendorDoubleLoadTest-ndk_platform",
- "libbinder_aidl_test_stub-ndk_platform",
+ "IBinderVendorDoubleLoadTest-ndk",
+ "libbinder_aidl_test_stub-ndk",
],
// critical that libbinder/libbinder_ndk are shared for VTS
shared_libs: [
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index cdd7c08..b03ed49 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -38,7 +38,7 @@
///
/// This struct encapsulates the generic C++ `sp<IBinder>` class. This wrapper
/// is untyped; typed interface access is implemented by the AIDL compiler.
-pub struct SpIBinder(*mut sys::AIBinder);
+pub struct SpIBinder(ptr::NonNull<sys::AIBinder>);
impl fmt::Debug for SpIBinder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -74,7 +74,7 @@
/// to an `AIBinder`, which will remain valid for the entire lifetime of the
/// `SpIBinder` (we keep a strong reference, and only decrement on drop).
pub(crate) unsafe fn from_raw(ptr: *mut sys::AIBinder) -> Option<Self> {
- ptr.as_mut().map(|p| Self(p))
+ ptr::NonNull::new(ptr).map(Self)
}
/// Extract a raw `AIBinder` pointer from this wrapper.
@@ -88,7 +88,7 @@
/// The SpIBinder object retains ownership of the AIBinder and the caller
/// should not attempt to free the returned pointer.
pub unsafe fn as_raw(&self) -> *mut sys::AIBinder {
- self.0
+ self.0.as_ptr()
}
/// Return true if this binder object is hosted in a different process than
@@ -176,13 +176,13 @@
// Safety: SpIBinder always holds a valid `AIBinder` pointer, so
// this pointer is always safe to pass to `AIBinder_lt` (null is
// also safe to pass to this function, but we should never do that).
- sys::AIBinder_lt(self.0, other.0)
+ sys::AIBinder_lt(self.0.as_ptr(), other.0.as_ptr())
};
let greater_than = unsafe {
// Safety: SpIBinder always holds a valid `AIBinder` pointer, so
// this pointer is always safe to pass to `AIBinder_lt` (null is
// also safe to pass to this function, but we should never do that).
- sys::AIBinder_lt(other.0, self.0)
+ sys::AIBinder_lt(other.0.as_ptr(), self.0.as_ptr())
};
if !less_than && !greater_than {
Ordering::Equal
@@ -202,7 +202,7 @@
impl PartialEq for SpIBinder {
fn eq(&self, other: &Self) -> bool {
- ptr::eq(self.0, other.0)
+ ptr::eq(self.0.as_ptr(), other.0.as_ptr())
}
}
@@ -214,7 +214,7 @@
// Safety: Cloning a strong reference must increment the reference
// count. We are guaranteed by the `SpIBinder` constructor
// invariants that `self.0` is always a valid `AIBinder` pointer.
- sys::AIBinder_incStrong(self.0);
+ sys::AIBinder_incStrong(self.0.as_ptr());
}
Self(self.0)
}
@@ -443,7 +443,7 @@
///
/// This struct encapsulates the generic C++ `wp<IBinder>` class. This wrapper
/// is untyped; typed interface access is implemented by the AIDL compiler.
-pub struct WpIBinder(*mut sys::AIBinder_Weak);
+pub struct WpIBinder(ptr::NonNull<sys::AIBinder_Weak>);
impl fmt::Debug for WpIBinder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -470,8 +470,7 @@
// valid pointer to an `AIBinder`.
sys::AIBinder_Weak_new(binder.as_native_mut())
};
- assert!(!ptr.is_null());
- Self(ptr)
+ Self(ptr::NonNull::new(ptr).expect("Unexpected null pointer from AIBinder_Weak_new"))
}
/// Promote this weak reference to a strong reference to the binder object.
@@ -481,7 +480,7 @@
// can pass this pointer to `AIBinder_Weak_promote`. Returns either
// null or an AIBinder owned by the caller, both of which are valid
// to pass to `SpIBinder::from_raw`.
- let ptr = sys::AIBinder_Weak_promote(self.0);
+ let ptr = sys::AIBinder_Weak_promote(self.0.as_ptr());
SpIBinder::from_raw(ptr)
}
}
@@ -496,13 +495,9 @@
//
// We get ownership of the returned pointer, so can construct a new
// WpIBinder object from it.
- sys::AIBinder_Weak_clone(self.0)
+ sys::AIBinder_Weak_clone(self.0.as_ptr())
};
- assert!(
- !ptr.is_null(),
- "Unexpected null pointer from AIBinder_Weak_clone"
- );
- Self(ptr)
+ Self(ptr::NonNull::new(ptr).expect("Unexpected null pointer from AIBinder_Weak_clone"))
}
}
@@ -513,14 +508,14 @@
// so this pointer is always safe to pass to `AIBinder_Weak_lt`
// (null is also safe to pass to this function, but we should never
// do that).
- sys::AIBinder_Weak_lt(self.0, other.0)
+ sys::AIBinder_Weak_lt(self.0.as_ptr(), other.0.as_ptr())
};
let greater_than = unsafe {
// Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
// so this pointer is always safe to pass to `AIBinder_Weak_lt`
// (null is also safe to pass to this function, but we should never
// do that).
- sys::AIBinder_Weak_lt(other.0, self.0)
+ sys::AIBinder_Weak_lt(other.0.as_ptr(), self.0.as_ptr())
};
if !less_than && !greater_than {
Ordering::Equal
@@ -551,7 +546,7 @@
unsafe {
// Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, so we
// know this pointer is safe to pass to `AIBinder_Weak_delete` here.
- sys::AIBinder_Weak_delete(self.0);
+ sys::AIBinder_Weak_delete(self.0.as_ptr());
}
}
}
@@ -716,10 +711,10 @@
/// `AIBinder`, so we can trivially extract this pointer here.
unsafe impl AsNative<sys::AIBinder> for SpIBinder {
fn as_native(&self) -> *const sys::AIBinder {
- self.0
+ self.0.as_ptr()
}
fn as_native_mut(&mut self) -> *mut sys::AIBinder {
- self.0
+ self.0.as_ptr()
}
}
diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp
index 607860f..ecc61f4 100644
--- a/libs/binder/rust/tests/Android.bp
+++ b/libs/binder/rust/tests/Android.bp
@@ -50,7 +50,7 @@
"libbinder_ndk",
],
static_libs: [
- "IBinderRustNdkInteropTest-ndk_platform",
+ "IBinderRustNdkInteropTest-ndk",
"libbinder_ndk_rust_interop",
],
test_suites: ["general-tests"],
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 24afcf6..13ea827 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -145,6 +145,7 @@
defaults: [
"binder_test_defaults",
"libbinder_ndk_host_user",
+ "libbinder_tls_shared_deps",
],
srcs: [
@@ -159,8 +160,9 @@
"liblog",
],
static_libs: [
+ "libbinder_tls_static",
"binderRpcTestIface-cpp",
- "binderRpcTestIface-ndk_platform",
+ "binderRpcTestIface-ndk",
],
test_suites: ["general-tests"],
require_root: true,
@@ -188,6 +190,33 @@
}
cc_test {
+ name: "binderRpcWireProtocolTest",
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ android: {
+ test_suites: ["vts"],
+ },
+ },
+ defaults: [
+ "binder_test_defaults",
+ ],
+ srcs: [
+ "binderRpcWireProtocolTest.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbase",
+ "libutils",
+ "libcutils",
+ "liblog",
+ ],
+ test_suites: ["general-tests"],
+}
+
+cc_test {
name: "binderThroughputTest",
defaults: ["binder_test_defaults"],
srcs: ["binderThroughputTest.cpp"],
@@ -296,7 +325,7 @@
],
static_libs: [
"binderStabilityTestIface-cpp",
- "binderStabilityTestIface-ndk_platform",
+ "binderStabilityTestIface-ndk",
],
test_suites: ["device-tests", "vts"],
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 15ccae9..7c405d3 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -31,6 +31,7 @@
#include <binder/RpcSession.h>
#include <binder/RpcTransport.h>
#include <binder/RpcTransportRaw.h>
+#include <binder/RpcTransportTls.h>
#include <gtest/gtest.h>
#include <chrono>
@@ -54,16 +55,18 @@
RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
const char* kLocalInetAddress = "127.0.0.1";
-enum class RpcSecurity { RAW };
+enum class RpcSecurity { RAW, TLS };
static inline std::vector<RpcSecurity> RpcSecurityValues() {
- return {RpcSecurity::RAW};
+ return {RpcSecurity::RAW, RpcSecurity::TLS};
}
static inline std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity) {
switch (rpcSecurity) {
case RpcSecurity::RAW:
return RpcTransportCtxFactoryRaw::make();
+ case RpcSecurity::TLS:
+ return RpcTransportCtxFactoryTls::make();
default:
LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", rpcSecurity);
}
@@ -519,7 +522,8 @@
status_t status;
for (size_t i = 0; i < options.numSessions; i++) {
- sp<RpcSession> session = RpcSession::make(newFactory(rpcSecurity));
+ sp<RpcSession> session =
+ RpcSession::make(newFactory(rpcSecurity), std::nullopt, std::nullopt);
session->setMaxThreads(options.numIncomingConnections);
switch (socketType) {
@@ -1204,7 +1208,8 @@
}
server->start();
- sp<RpcSession> session = RpcSession::make(RpcTransportCtxFactoryRaw::make());
+ sp<RpcSession> session =
+ RpcSession::make(RpcTransportCtxFactoryRaw::make(), std::nullopt, std::nullopt);
status_t status = session->setupVsockClient(VMADDR_CID_LOCAL, vsockPort);
while (!server->shutdown()) usleep(10000);
ALOGE("Detected vsock loopback supported: %s", statusToString(status).c_str());
diff --git a/libs/binder/tests/binderRpcWireProtocolTest.cpp b/libs/binder/tests/binderRpcWireProtocolTest.cpp
new file mode 100644
index 0000000..46e9630
--- /dev/null
+++ b/libs/binder/tests/binderRpcWireProtocolTest.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#include <android-base/hex.h>
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <binder/Parcel.h>
+#include <binder/RpcSession.h>
+#include <gtest/gtest.h>
+
+#include "../Debug.h"
+
+namespace android {
+
+static const int32_t kInt32Array[] = {-1, 0, 17};
+static const uint8_t kByteArray[] = {0, 17, 255};
+enum EnumInt8 : int8_t { Int8A, Int8B };
+enum EnumInt32 : int32_t { Int32A, Int32B };
+enum EnumInt64 : int64_t { Int64A, Int64B };
+struct AParcelable : Parcelable {
+ status_t writeToParcel(Parcel* parcel) const { return parcel->writeInt32(37); }
+ status_t readFromParcel(const Parcel*) { return OK; }
+};
+
+// clang-format off
+constexpr size_t kFillFunIndexLineBase = __LINE__ + 2;
+static const std::vector<std::function<void(Parcel* p)>> kFillFuns {
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInterfaceToken(String16(u"tok"))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt32(-1)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt32(0)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt32(17)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint32(0)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint32(1)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint32(10003)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt64(-1)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt64(0)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt64(17)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint64(0)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint64(1)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint64(10003)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeFloat(0.0f)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeFloat(0.1f)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeFloat(9.1f)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeDouble(0.0)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeDouble(0.1)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeDouble(9.1)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeCString("")); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeCString("a")); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeCString("baba")); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString8(String8(""))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString8(String8("a"))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString8(String8("baba"))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString16(String16(u""))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString16(String16(u"a"))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString16(String16(u"baba"))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeStrongBinder(nullptr)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt32Array(arraysize(kInt32Array), kInt32Array)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByteArray(arraysize(kByteArray), kByteArray)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeBool(true)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeBool(false)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeChar('a')); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeChar('?')); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeChar('\0')); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByte(-128)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByte(0)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByte(127)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8AsUtf16(std::string(""))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8AsUtf16(std::string("a"))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8AsUtf16(std::string("abab"))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8AsUtf16(std::nullopt)); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8AsUtf16(std::optional<std::string>(""))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8AsUtf16(std::optional<std::string>("a"))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8AsUtf16(std::optional<std::string>("abab"))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByteVector(std::optional<std::vector<int8_t>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByteVector(std::optional<std::vector<int8_t>>({-1, 0, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByteVector(std::vector<int8_t>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByteVector(std::vector<int8_t>({-1, 0, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByteVector(std::optional<std::vector<uint8_t>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByteVector(std::optional<std::vector<uint8_t>>({0, 1, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByteVector(std::vector<uint8_t>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeByteVector(std::vector<uint8_t>({0, 1, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt32Vector(std::optional<std::vector<int32_t>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt32Vector(std::optional<std::vector<int32_t>>({-1, 0, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt32Vector(std::vector<int32_t>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt32Vector(std::vector<int32_t>({-1, 0, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt64Vector(std::optional<std::vector<int64_t>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt64Vector(std::optional<std::vector<int64_t>>({-1, 0, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt64Vector(std::vector<int64_t>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeInt64Vector(std::vector<int64_t>({-1, 0, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint64Vector(std::optional<std::vector<uint64_t>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint64Vector(std::optional<std::vector<uint64_t>>({0, 1, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint64Vector(std::vector<uint64_t>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUint64Vector(std::vector<uint64_t>({0, 1, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeFloatVector(std::optional<std::vector<float>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeFloatVector(std::optional<std::vector<float>>({0.0f, 0.1f, 9.1f}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeFloatVector(std::vector<float>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeFloatVector(std::vector<float>({0.0f, 0.1f, 9.1f}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeDoubleVector(std::optional<std::vector<double>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeDoubleVector(std::optional<std::vector<double>>({0.0, 0.1, 9.1}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeDoubleVector(std::vector<double>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeDoubleVector(std::vector<double>({0.0, 0.1, 9.1}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeBoolVector(std::optional<std::vector<bool>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeBoolVector(std::optional<std::vector<bool>>({true, false}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeBoolVector(std::vector<bool>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeBoolVector(std::vector<bool>({true, false}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeCharVector(std::optional<std::vector<char16_t>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeCharVector(std::optional<std::vector<char16_t>>({'a', '\0', '?'}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeCharVector(std::vector<char16_t>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeCharVector(std::vector<char16_t>({'a', '\0', '?'}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString16Vector(std::optional<std::vector<std::optional<String16>>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString16Vector(std::optional<std::vector<std::optional<String16>>>({std::nullopt, String16(), String16(u"a")}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString16Vector(std::vector<std::optional<String16>>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeString16Vector(std::vector<std::optional<String16>>({std::nullopt, String16(), String16(u"a")}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8VectorAsUtf16Vector(std::optional<std::vector<std::optional<std::string>>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8VectorAsUtf16Vector(std::optional<std::vector<std::optional<std::string>>>({std::nullopt, std::string(), std::string("a")}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8VectorAsUtf16Vector(std::vector<std::optional<std::string>>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeUtf8VectorAsUtf16Vector(std::vector<std::optional<std::string>>({std::nullopt, std::string(), std::string("a")}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeStrongBinderVector(std::optional<std::vector<sp<IBinder>>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeStrongBinderVector(std::optional<std::vector<sp<IBinder>>>({nullptr}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeStrongBinderVector(std::vector<sp<IBinder>>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeStrongBinderVector(std::vector<sp<IBinder>>({nullptr}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeEnumVector(std::optional<std::vector<EnumInt8>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeEnumVector(std::optional<std::vector<EnumInt8>>({Int8A, Int8B}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeEnumVector(std::vector<EnumInt8>({Int8A, Int8B}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeEnumVector(std::optional<std::vector<EnumInt32>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeEnumVector(std::optional<std::vector<EnumInt32>>({Int32A, Int32B}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeEnumVector(std::vector<EnumInt32>({Int32A, Int32B}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeEnumVector(std::optional<std::vector<EnumInt64>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeEnumVector(std::optional<std::vector<EnumInt64>>({Int64A, Int64B}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeEnumVector(std::vector<EnumInt64>({Int64A, Int64B}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeParcelableVector(std::optional<std::vector<std::optional<AParcelable>>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeParcelableVector(std::optional<std::vector<std::optional<AParcelable>>>({AParcelable()}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeParcelableVector(std::vector<AParcelable>({AParcelable()}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeNullableParcelable(std::optional<AParcelable>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeNullableParcelable(std::optional<AParcelable>(AParcelable()))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeParcelable(AParcelable())); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeVectorSize(std::vector<int32_t>({0, 1, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeVectorSize(std::vector<AParcelable>({}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeVectorSize(std::optional<std::vector<int32_t>>(std::nullopt))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeVectorSize(std::optional<std::vector<int32_t>>({0, 1, 17}))); },
+ [](Parcel* p) { ASSERT_EQ(OK, p->writeNoException()); },
+};
+// clang-format on
+
+static void setParcelForRpc(Parcel* p, uint32_t version) {
+ auto session = RpcSession::make();
+ CHECK(session->setProtocolVersion(version));
+ CHECK_EQ(OK, session->addNullDebuggingClient());
+ p->markForRpc(session);
+}
+
+static std::string buildRepr(uint32_t version) {
+ std::string result;
+ for (size_t i = 0; i < kFillFuns.size(); i++) {
+ if (i != 0) result += "|";
+ Parcel p;
+ setParcelForRpc(&p, version);
+ kFillFuns[i](&p);
+
+ result += base::HexString(p.data(), p.dataSize());
+ }
+ return result;
+}
+
+static void checkRepr(const std::string& repr, uint32_t version) {
+ const std::string actualRepr = buildRepr(version);
+
+ auto expected = base::Split(repr, "|");
+ ASSERT_EQ(expected.size(), kFillFuns.size());
+
+ auto actual = base::Split(actualRepr, "|");
+ ASSERT_EQ(actual.size(), kFillFuns.size());
+
+ for (size_t i = 0; i < kFillFuns.size(); i++) {
+ EXPECT_EQ(expected[i], actual[i])
+ << "Format mismatch, see " __FILE__ " line " << (kFillFunIndexLineBase + i);
+ }
+
+ // same check as in the loop, but the above error is more clear to debug,
+ // and this error is more clear to be able to update the source file here.
+ EXPECT_EQ(repr, actualRepr);
+}
+
+const std::string kCurrentRepr =
+ "0300000074006f006b000000|ffffffff|00000000|11000000|00000000|01000000|13270000|"
+ "ffffffffffffffff|0000000000000000|1100000000000000|0000000000000000|0100000000000000|"
+ "1327000000000000|00000000|cdcccc3d|9a991141|0000000000000000|9a9999999999b93f|"
+ "3333333333332240|00000000|61000000|6261626100000000|0000000000000000|0100000061000000|"
+ "040000006261626100000000|0000000000000000|0100000061000000|"
+ "04000000620061006200610000000000|0000000000000000|03000000ffffffff0000000011000000|"
+ "030000000011ff00|01000000|00000000|61000000|3f000000|00000000|80ffffff|00000000|7f000000|"
+ "0000000000000000|0100000061000000|04000000610062006100620000000000|ffffffff|"
+ "0000000000000000|0100000061000000|04000000610062006100620000000000|ffffffff|"
+ "03000000ff001100|00000000|03000000ff001100|ffffffff|0300000000011100|00000000|"
+ "0300000000011100|ffffffff|03000000ffffffff0000000011000000|00000000|"
+ "03000000ffffffff0000000011000000|ffffffff|"
+ "03000000ffffffffffffffff00000000000000001100000000000000|00000000|"
+ "03000000ffffffffffffffff00000000000000001100000000000000|ffffffff|"
+ "03000000000000000000000001000000000000001100000000000000|00000000|"
+ "03000000000000000000000001000000000000001100000000000000|ffffffff|"
+ "0300000000000000cdcccc3d9a991141|00000000|0300000000000000cdcccc3d9a991141|ffffffff|"
+ "0300000000000000000000009a9999999999b93f3333333333332240|00000000|"
+ "0300000000000000000000009a9999999999b93f3333333333332240|ffffffff|"
+ "020000000100000000000000|00000000|020000000100000000000000|ffffffff|"
+ "0300000061000000000000003f000000|00000000|0300000061000000000000003f000000|ffffffff|"
+ "03000000ffffffff00000000000000000100000061000000|00000000|"
+ "03000000ffffffff00000000000000000100000061000000|ffffffff|"
+ "03000000ffffffff00000000000000000100000061000000|00000000|"
+ "03000000ffffffff00000000000000000100000061000000|ffffffff|010000000000000000000000|"
+ "00000000|010000000000000000000000|ffffffff|0200000000010000|0200000000010000|ffffffff|"
+ "020000000000000001000000|020000000000000001000000|ffffffff|"
+ "0200000000000000000000000100000000000000|0200000000000000000000000100000000000000|"
+ "ffffffff|010000000100000025000000|010000000100000025000000|00000000|0100000025000000|"
+ "0100000025000000|03000000|00000000|ffffffff|03000000|00000000";
+
+TEST(RpcWire, CurrentVersion) {
+ checkRepr(kCurrentRepr, RPC_WIRE_PROTOCOL_VERSION);
+}
+
+static_assert(RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL,
+ "you better update this test!");
+
+TEST(RpcWire, ReleaseBranchHasFrozenRpcWireProtocol) {
+ if (RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL) {
+ EXPECT_FALSE(base::GetProperty("ro.build.version.codename", "") == "REL")
+ << "Binder RPC wire protocol must be frozen on a release branch!";
+ }
+}
+
+TEST(RpcWire, IfNotExperimentalCodeHasNoExperimentalFeatures) {
+ if (RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL) {
+ GTEST_SKIP() << "Version is experimental, so experimental features are okay.";
+ }
+
+ // if we set the wire protocol version to experimental, none of the code
+ // should introduce a difference (if this fails, it means we have features
+ // which are enabled under experimental mode, but we aren't actually using
+ // or testing them!)
+ checkRepr(kCurrentRepr, RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
+}
+
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 8bf04cc..7fd9f6b 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -36,7 +36,8 @@
void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider) {
if (provider.ConsumeBool()) {
- auto session = RpcSession::make(RpcTransportCtxFactoryRaw::make());
+ auto session =
+ RpcSession::make(RpcTransportCtxFactoryRaw::make(), std::nullopt, std::nullopt);
CHECK_EQ(OK, session->addNullDebuggingClient());
p->markForRpc(session);
fillRandomParcelData(p, std::move(provider));
diff --git a/libs/binder/tests/rpc_fuzzer/Android.bp b/libs/binder/tests/rpc_fuzzer/Android.bp
index 1c75306..9323bd5 100644
--- a/libs/binder/tests/rpc_fuzzer/Android.bp
+++ b/libs/binder/tests/rpc_fuzzer/Android.bp
@@ -22,18 +22,19 @@
"libbase",
"libcutils",
"liblog",
- "libutils",
],
target: {
android: {
shared_libs: [
"libbinder",
+ "libutils",
],
},
host: {
static_libs: [
"libbinder",
+ "libutils",
],
},
},
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index a0032ae..cda9e19 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -52,14 +52,14 @@
],
shared_libs: [
- "android.hardware.graphics.common-V2-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk",
"android.hardware.graphics.mapper@4.0",
"libhidlbase",
"liblog",
],
export_shared_lib_headers: [
- "android.hardware.graphics.common-V2-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk",
"android.hardware.graphics.mapper@4.0",
"libhidlbase",
],
diff --git a/libs/input/VelocityControl.cpp b/libs/input/VelocityControl.cpp
index 0c3ad63..03c49cc 100644
--- a/libs/input/VelocityControl.cpp
+++ b/libs/input/VelocityControl.cpp
@@ -18,7 +18,7 @@
//#define LOG_NDEBUG 0
// Log debug messages about acceleration.
-#define DEBUG_ACCELERATION 0
+static constexpr bool DEBUG_ACCELERATION = false;
#include <math.h>
#include <limits.h>
@@ -52,12 +52,10 @@
void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
if (eventTime >= mLastMovementTime + STOP_TIME) {
-#if DEBUG_ACCELERATION
- if (mLastMovementTime != LLONG_MIN) {
- ALOGD("VelocityControl: stopped, last movement was %0.3fms ago",
- (eventTime - mLastMovementTime) * 0.000001f);
- }
-#endif
+ if (DEBUG_ACCELERATION && mLastMovementTime != LLONG_MIN) {
+ ALOGD("VelocityControl: stopped, last movement was %0.3fms ago",
+ (eventTime - mLastMovementTime) * 0.000001f);
+ }
reset();
}
@@ -85,19 +83,20 @@
* (mParameters.acceleration - 1);
}
-#if DEBUG_ACCELERATION
- ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
- "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
- mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
- mParameters.acceleration,
- vx, vy, speed, scale / mParameters.scale);
-#endif
+ if (DEBUG_ACCELERATION) {
+ ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
+ "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
+ mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
+ mParameters.acceleration,
+ vx, vy, speed, scale / mParameters.scale);
+ }
+
} else {
-#if DEBUG_ACCELERATION
- ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
- mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
- mParameters.acceleration);
-#endif
+ if (DEBUG_ACCELERATION) {
+ ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
+ mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
+ mParameters.acceleration);
+ }
}
if (deltaX) {
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 07760ab..26c874e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -89,7 +89,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.allocator@4.0",
- "android.hardware.graphics.common-V2-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk",
"android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
@@ -106,7 +106,7 @@
export_shared_lib_headers: [
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.common-V2-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk",
"android.hardware.graphics.mapper@4.0",
"libgralloctypes",
],
diff --git a/services/memtrackproxy/Android.bp b/services/memtrackproxy/Android.bp
index 7d78f3b..3233cc9 100644
--- a/services/memtrackproxy/Android.bp
+++ b/services/memtrackproxy/Android.bp
@@ -32,7 +32,7 @@
"libcutils",
"libutils",
"android.hardware.memtrack@1.0",
- "android.hardware.memtrack-V1-ndk_platform",
+ "android.hardware.memtrack-V1-ndk",
],
srcs: [
"MemtrackProxy.cpp",
@@ -45,6 +45,6 @@
],
export_shared_lib_headers: [
"android.hardware.memtrack@1.0",
- "android.hardware.memtrack-V1-ndk_platform",
+ "android.hardware.memtrack-V1-ndk",
],
}
diff --git a/services/memtrackproxy/test/Android.bp b/services/memtrackproxy/test/Android.bp
index f943761..1dc21bf 100644
--- a/services/memtrackproxy/test/Android.bp
+++ b/services/memtrackproxy/test/Android.bp
@@ -29,7 +29,7 @@
shared_libs: [
"libbinder_ndk",
"libmemtrackproxy",
- "android.hardware.memtrack-V1-ndk_platform",
+ "android.hardware.memtrack-V1-ndk",
],
test_suites: ["general-tests"],
require_root: true,
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 15744a1..81e39c7 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -53,7 +53,7 @@
"libtrace_proto",
],
shared_libs: [
- "android.hardware.graphics.common-V2-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk",
"android.hardware.graphics.common@1.2",
"android.hardware.graphics.composer@2.1",
"libandroid",