Merge "Add servicedispatcher"
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 424299d..509ee0e 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -83,7 +83,7 @@
*
* To clear a previous process binding, invoke with NETWORK_UNSPECIFIED.
*
- * This is the equivalent of: [android.net.ConnectivityManager#setProcessDefaultNetwork()](https://developer.android.com/reference/android/net/ConnectivityManager.html#setProcessDefaultNetwork(android.net.Network))
+ * This is the equivalent of: [android.net.ConnectivityManager#bindProcessToNetwork()](https://developer.android.com/reference/android/net/ConnectivityManager.html#bindProcessToNetwork(android.net.Network))
*
* Available since API level 23.
*/
@@ -91,6 +91,41 @@
/**
+ * Gets the |network| bound to the current process, as per android_setprocnetwork.
+ *
+ * This is the equivalent of: [android.net.ConnectivityManager#getBoundNetworkForProcess()](https://developer.android.com/reference/android/net/ConnectivityManager.html#getBoundNetworkForProcess(android.net.Network))
+ * Returns 0 on success, or -1 setting errno to EINVAL if a null pointer is
+ * passed in.
+ *
+ *
+ * Available since API level 31.
+ */
+int android_getprocnetwork(net_handle_t *network) __INTRODUCED_IN(31);
+
+/**
+ * Binds domain name resolutions performed by this process to |network|.
+ * android_setprocnetwork takes precedence over this setting.
+ *
+ * To clear a previous process binding, invoke with NETWORK_UNSPECIFIED.
+ * On success 0 is returned. On error -1 is returned, and errno is set.
+ *
+ * Available since API level 31.
+ */
+int android_setprocdns(net_handle_t network) __INTRODUCED_IN(31);
+
+/**
+ * Gets the |network| to which domain name resolutions are bound on the
+ * current process.
+ *
+ * Returns 0 on success, or -1 setting errno to EINVAL if a null pointer is
+ * passed in.
+ *
+ * Available since API level 31.
+ */
+int android_getprocdns(net_handle_t *network) __INTRODUCED_IN(31);
+
+
+/**
* Perform hostname resolution via the DNS servers associated with |network|.
*
* All arguments (apart from |network|) are used identically as those passed
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 9be05d3..b9c8d20 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -71,6 +71,8 @@
cc_library {
name: "libbinder",
+ version_script: "libbinder.map",
+
// for vndbinder
vendor_available: true,
vndk: {
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index c83c383..415b44e 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -197,9 +197,7 @@
// ---------------------------------------------------------------------------
-BBinder::BBinder() : mExtras(nullptr), mStability(0)
-{
-}
+BBinder::BBinder() : mExtras(nullptr), mStability(0), mParceled(false) {}
bool BBinder::isBinderAlive() const
{
@@ -322,6 +320,10 @@
void BBinder::setRequestingSid(bool requestingSid)
{
+ ALOGW_IF(mParceled,
+ "setRequestingSid() should not be called after a binder object "
+ "is parceled/sent to another process");
+
Extras* e = mExtras.load(std::memory_order_acquire);
if (!e) {
@@ -344,6 +346,10 @@
}
void BBinder::setMinSchedulerPolicy(int policy, int priority) {
+ ALOGW_IF(mParceled,
+ "setMinSchedulerPolicy() should not be called after a binder object "
+ "is parceled/sent to another process");
+
switch (policy) {
case SCHED_NORMAL:
LOG_ALWAYS_FATAL_IF(priority < -20 || priority > 19, "Invalid priority for SCHED_NORMAL: %d", priority);
@@ -391,6 +397,10 @@
}
void BBinder::setInheritRt(bool inheritRt) {
+ ALOGW_IF(mParceled,
+ "setInheritRt() should not be called after a binder object "
+ "is parceled/sent to another process");
+
Extras* e = mExtras.load(std::memory_order_acquire);
if (!e) {
@@ -410,10 +420,22 @@
}
void BBinder::setExtension(const sp<IBinder>& extension) {
+ ALOGW_IF(mParceled,
+ "setExtension() should not be called after a binder object "
+ "is parceled/sent to another process");
+
Extras* e = getOrCreateExtras();
e->mExtension = extension;
}
+bool BBinder::wasParceled() {
+ return mParceled;
+}
+
+void BBinder::setParceled() {
+ mParceled = true;
+}
+
status_t BBinder::setRpcClientDebug(const Parcel& data) {
if constexpr (!kEnableRpcDevServers) {
ALOGW("%s: disallowed because RPC is not enabled", __PRETTY_FUNCTION__);
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 47dd32e..d421060 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -129,8 +129,7 @@
return checkCallingPermission(permission, nullptr, nullptr);
}
-static String16 _permission("permission");
-
+static StaticString16 _permission(u"permission");
bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid)
{
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index d19b4d8..232a70c 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -173,8 +173,8 @@
status_t Parcel::finishFlattenBinder(const sp<IBinder>& binder)
{
internal::Stability::tryMarkCompilationUnit(binder.get());
- auto category = internal::Stability::getCategory(binder.get());
- return writeInt32(category.repr());
+ int16_t rep = internal::Stability::getCategory(binder.get()).repr();
+ return writeInt32(rep);
}
status_t Parcel::finishUnflattenBinder(
@@ -184,7 +184,8 @@
status_t status = readInt32(&stability);
if (status != OK) return status;
- status = internal::Stability::setRepr(binder.get(), stability, true /*log*/);
+ status = internal::Stability::setRepr(binder.get(), static_cast<int16_t>(stability),
+ true /*log*/);
if (status != OK) return status;
*out = binder;
@@ -195,8 +196,11 @@
return (priority & FLAT_BINDER_FLAG_PRIORITY_MASK) | ((policy & 3) << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT);
}
-status_t Parcel::flattenBinder(const sp<IBinder>& binder)
-{
+status_t Parcel::flattenBinder(const sp<IBinder>& binder) {
+ BBinder* local = nullptr;
+ if (binder) local = binder->localBinder();
+ if (local) local->setParceled();
+
if (isForRpc()) {
if (binder) {
status_t status = writeInt32(1); // non-null
@@ -222,7 +226,6 @@
}
if (binder != nullptr) {
- BBinder *local = binder->localBinder();
if (!local) {
BpBinder *proxy = binder->remoteBinder();
if (proxy == nullptr) {
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 5ffee06..2f378da 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -153,7 +153,22 @@
status_t status;
while ((status = mShutdownTrigger->triggerablePollRead(mServer)) == OK) {
- (void)acceptOne();
+ unique_fd clientFd(TEMP_FAILURE_RETRY(
+ accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
+
+ if (clientFd < 0) {
+ ALOGE("Could not accept4 socket: %s", strerror(errno));
+ continue;
+ }
+ LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
+
+ {
+ std::lock_guard<std::mutex> _l(mLock);
+ std::thread thread =
+ std::thread(&RpcServer::establishConnection, sp<RpcServer>::fromExisting(this),
+ std::move(clientFd));
+ mConnectingThreads[thread.get_id()] = std::move(thread);
+ }
}
LOG_RPC_DETAIL("RpcServer::join exiting with %s", statusToString(status).c_str());
@@ -164,26 +179,6 @@
mShutdownCv.notify_all();
}
-bool RpcServer::acceptOne() {
- unique_fd clientFd(
- TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
-
- if (clientFd < 0) {
- ALOGE("Could not accept4 socket: %s", strerror(errno));
- return false;
- }
- LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
-
- {
- std::lock_guard<std::mutex> _l(mLock);
- std::thread thread = std::thread(&RpcServer::establishConnection,
- sp<RpcServer>::fromExisting(this), std::move(clientFd));
- mConnectingThreads[thread.get_id()] = std::move(thread);
- }
-
- return true;
-}
-
bool RpcServer::shutdown() {
std::unique_lock<std::mutex> _l(mLock);
if (mShutdownTrigger == nullptr) {
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index a27dff5..c563377 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -240,7 +240,8 @@
sp<RpcConnection> connection = session->assignServerToThisThread(std::move(client));
while (true) {
- status_t error = session->state()->getAndExecuteCommand(connection->fd, session);
+ status_t error = session->state()->getAndExecuteCommand(connection->fd, session,
+ RpcState::CommandType::ANY);
if (error != OK) {
LOG_RPC_DETAIL("Binder connection thread closing w/ status %s",
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 76df970..93f1529 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -134,6 +134,15 @@
void RpcState::dump() {
std::lock_guard<std::mutex> _l(mNodeMutex);
+ dumpLocked();
+}
+
+void RpcState::terminate() {
+ std::unique_lock<std::mutex> _l(mNodeMutex);
+ terminate(_l);
+}
+
+void RpcState::dumpLocked() {
ALOGE("DUMP OF RpcState %p", this);
ALOGE("DUMP OF RpcState (%zu nodes)", mNodeForAddress.size());
for (const auto& [address, node] : mNodeForAddress) {
@@ -161,10 +170,10 @@
ALOGE("END DUMP OF RpcState");
}
-void RpcState::terminate() {
+void RpcState::terminate(std::unique_lock<std::mutex>& lock) {
if (SHOULD_LOG_RPC_DETAIL) {
ALOGE("RpcState::terminate()");
- dump();
+ dumpLocked();
}
// if the destructor of a binder object makes another RPC call, then calling
@@ -172,20 +181,20 @@
// mNodeMutex is no longer taken.
std::vector<sp<IBinder>> tempHoldBinder;
- {
- std::lock_guard<std::mutex> _l(mNodeMutex);
- mTerminated = true;
- for (auto& [address, node] : mNodeForAddress) {
- sp<IBinder> binder = node.binder.promote();
- LOG_ALWAYS_FATAL_IF(binder == nullptr, "Binder %p expected to be owned.", binder.get());
+ mTerminated = true;
+ for (auto& [address, node] : mNodeForAddress) {
+ sp<IBinder> binder = node.binder.promote();
+ LOG_ALWAYS_FATAL_IF(binder == nullptr, "Binder %p expected to be owned.", binder.get());
- if (node.sentRef != nullptr) {
- tempHoldBinder.push_back(node.sentRef);
- }
+ if (node.sentRef != nullptr) {
+ tempHoldBinder.push_back(node.sentRef);
}
-
- mNodeForAddress.clear();
}
+
+ mNodeForAddress.clear();
+
+ lock.unlock();
+ tempHoldBinder.clear(); // explicit
}
RpcState::CommandData::CommandData(size_t size) : mSize(size) {
@@ -341,52 +350,57 @@
uint64_t asyncNumber = 0;
if (!address.isZero()) {
- std::lock_guard<std::mutex> _l(mNodeMutex);
+ std::unique_lock<std::mutex> _l(mNodeMutex);
if (mTerminated) return DEAD_OBJECT; // avoid fatal only, otherwise races
auto it = mNodeForAddress.find(address);
LOG_ALWAYS_FATAL_IF(it == mNodeForAddress.end(), "Sending transact on unknown address %s",
address.toString().c_str());
if (flags & IBinder::FLAG_ONEWAY) {
- asyncNumber = it->second.asyncNumber++;
+ asyncNumber = it->second.asyncNumber;
+ if (!nodeProgressAsyncNumber(&it->second, _l)) return DEAD_OBJECT;
}
}
+ LOG_ALWAYS_FATAL_IF(std::numeric_limits<int32_t>::max() - sizeof(RpcWireHeader) -
+ sizeof(RpcWireTransaction) <
+ data.dataSize(),
+ "Too much data %zu", data.dataSize());
+
+ RpcWireHeader command{
+ .command = RPC_COMMAND_TRANSACT,
+ .bodySize = static_cast<uint32_t>(sizeof(RpcWireTransaction) + data.dataSize()),
+ };
RpcWireTransaction transaction{
.address = address.viewRawEmbedded(),
.code = code,
.flags = flags,
.asyncNumber = asyncNumber,
};
-
- CommandData transactionData(sizeof(RpcWireTransaction) + data.dataSize());
+ CommandData transactionData(sizeof(RpcWireHeader) + sizeof(RpcWireTransaction) +
+ data.dataSize());
if (!transactionData.valid()) {
return NO_MEMORY;
}
- memcpy(transactionData.data() + 0, &transaction, sizeof(RpcWireTransaction));
- memcpy(transactionData.data() + sizeof(RpcWireTransaction), data.data(), data.dataSize());
+ memcpy(transactionData.data() + 0, &command, sizeof(RpcWireHeader));
+ memcpy(transactionData.data() + sizeof(RpcWireHeader), &transaction,
+ sizeof(RpcWireTransaction));
+ memcpy(transactionData.data() + sizeof(RpcWireHeader) + sizeof(RpcWireTransaction), data.data(),
+ data.dataSize());
- if (transactionData.size() > std::numeric_limits<uint32_t>::max()) {
- ALOGE("Transaction size too big %zu", transactionData.size());
- return BAD_VALUE;
- }
-
- RpcWireHeader command{
- .command = RPC_COMMAND_TRANSACT,
- .bodySize = static_cast<uint32_t>(transactionData.size()),
- };
-
- if (status_t status = rpcSend(fd, "transact header", &command, sizeof(command)); status != OK)
- return status;
if (status_t status =
- rpcSend(fd, "command body", transactionData.data(), transactionData.size());
+ rpcSend(fd, "transaction", transactionData.data(), transactionData.size());
status != OK)
return status;
if (flags & IBinder::FLAG_ONEWAY) {
LOG_RPC_DETAIL("Oneway command, so no longer waiting on %d", fd.get());
- return OK; // do not wait for result
+
+ // Do not wait on result.
+ // However, too many oneway calls may cause refcounts to build up and fill up the socket,
+ // so process those.
+ return drainCommands(fd, session, CommandType::CONTROL_ONLY);
}
LOG_ALWAYS_FATAL_IF(reply == nullptr, "Reply parcel must be used for synchronous transaction.");
@@ -413,7 +427,8 @@
if (command.command == RPC_COMMAND_REPLY) break;
- if (status_t status = processServerCommand(fd, session, command); status != OK)
+ if (status_t status = processServerCommand(fd, session, command, CommandType::ANY);
+ status != OK)
return status;
}
@@ -453,9 +468,8 @@
addr.toString().c_str());
it->second.timesRecd--;
- if (it->second.timesRecd == 0 && it->second.timesSent == 0) {
- mNodeForAddress.erase(it);
- }
+ LOG_ALWAYS_FATAL_IF(nullptr != tryEraseNode(it),
+ "Bad state. RpcState shouldn't own received binder");
}
RpcWireHeader cmd = {
@@ -471,7 +485,8 @@
return OK;
}
-status_t RpcState::getAndExecuteCommand(const base::unique_fd& fd, const sp<RpcSession>& session) {
+status_t RpcState::getAndExecuteCommand(const base::unique_fd& fd, const sp<RpcSession>& session,
+ CommandType type) {
LOG_RPC_DETAIL("getAndExecuteCommand on fd %d", fd.get());
RpcWireHeader command;
@@ -479,11 +494,21 @@
status != OK)
return status;
- return processServerCommand(fd, session, command);
+ return processServerCommand(fd, session, command, type);
+}
+
+status_t RpcState::drainCommands(const base::unique_fd& fd, const sp<RpcSession>& session,
+ CommandType type) {
+ uint8_t buf;
+ while (0 < TEMP_FAILURE_RETRY(recv(fd.get(), &buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT))) {
+ status_t status = getAndExecuteCommand(fd, session, type);
+ if (status != OK) return status;
+ }
+ return OK;
}
status_t RpcState::processServerCommand(const base::unique_fd& fd, const sp<RpcSession>& session,
- const RpcWireHeader& command) {
+ const RpcWireHeader& command, CommandType type) {
IPCThreadState* kernelBinderState = IPCThreadState::selfOrNull();
IPCThreadState::SpGuard spGuard{
.address = __builtin_frame_address(0),
@@ -501,6 +526,7 @@
switch (command.command) {
case RPC_COMMAND_TRANSACT:
+ if (type != CommandType::ANY) return BAD_TYPE;
return processTransact(fd, session, command);
case RPC_COMMAND_DEC_STRONG:
return processDecStrong(fd, session, command);
@@ -681,13 +707,7 @@
// last refcount dropped after this transaction happened
if (it == mNodeForAddress.end()) return OK;
- // note - only updated now, instead of later, so that other threads
- // will queue any later transactions
-
- // TODO(b/183140903): support > 2**64 async transactions
- // (we can do this by allowing asyncNumber to wrap, since we
- // don't expect more than 2**64 simultaneous transactions)
- it->second.asyncNumber++;
+ if (!nodeProgressAsyncNumber(&it->second, _l)) return DEAD_OBJECT;
if (it->second.asyncTodo.size() == 0) return OK;
if (it->second.asyncTodo.top().asyncNumber == it->second.asyncNumber) {
@@ -711,35 +731,29 @@
return OK;
}
+ LOG_ALWAYS_FATAL_IF(std::numeric_limits<int32_t>::max() - sizeof(RpcWireHeader) -
+ sizeof(RpcWireReply) <
+ reply.dataSize(),
+ "Too much data for reply %zu", reply.dataSize());
+
+ RpcWireHeader cmdReply{
+ .command = RPC_COMMAND_REPLY,
+ .bodySize = static_cast<uint32_t>(sizeof(RpcWireReply) + reply.dataSize()),
+ };
RpcWireReply rpcReply{
.status = replyStatus,
};
- CommandData replyData(sizeof(RpcWireReply) + reply.dataSize());
+ CommandData replyData(sizeof(RpcWireHeader) + sizeof(RpcWireReply) + reply.dataSize());
if (!replyData.valid()) {
return NO_MEMORY;
}
- memcpy(replyData.data() + 0, &rpcReply, sizeof(RpcWireReply));
- memcpy(replyData.data() + sizeof(RpcWireReply), reply.data(), reply.dataSize());
+ memcpy(replyData.data() + 0, &cmdReply, sizeof(RpcWireHeader));
+ memcpy(replyData.data() + sizeof(RpcWireHeader), &rpcReply, sizeof(RpcWireReply));
+ memcpy(replyData.data() + sizeof(RpcWireHeader) + sizeof(RpcWireReply), reply.data(),
+ reply.dataSize());
- if (replyData.size() > std::numeric_limits<uint32_t>::max()) {
- ALOGE("Reply size too big %zu", transactionData.size());
- terminate();
- return BAD_VALUE;
- }
-
- RpcWireHeader cmdReply{
- .command = RPC_COMMAND_REPLY,
- .bodySize = static_cast<uint32_t>(replyData.size()),
- };
-
- if (status_t status = rpcSend(fd, "reply header", &cmdReply, sizeof(RpcWireHeader));
- status != OK)
- return status;
- if (status_t status = rpcSend(fd, "reply body", replyData.data(), replyData.size());
- status != OK)
- return status;
- return OK;
+ return rpcSend(fd, "reply", replyData.data(), replyData.size());
}
status_t RpcState::processDecStrong(const base::unique_fd& fd, const sp<RpcSession>& session,
@@ -788,22 +802,40 @@
LOG_ALWAYS_FATAL_IF(it->second.sentRef == nullptr, "Inconsistent state, lost ref for %s",
addr.toString().c_str());
- sp<IBinder> tempHold;
-
it->second.timesSent--;
- if (it->second.timesSent == 0) {
- tempHold = it->second.sentRef;
- it->second.sentRef = nullptr;
-
- if (it->second.timesRecd == 0) {
- mNodeForAddress.erase(it);
- }
- }
-
+ sp<IBinder> tempHold = tryEraseNode(it);
_l.unlock();
tempHold = nullptr; // destructor may make binder calls on this session
return OK;
}
+sp<IBinder> RpcState::tryEraseNode(std::map<RpcAddress, BinderNode>::iterator& it) {
+ sp<IBinder> ref;
+
+ if (it->second.timesSent == 0) {
+ ref = std::move(it->second.sentRef);
+
+ if (it->second.timesRecd == 0) {
+ LOG_ALWAYS_FATAL_IF(!it->second.asyncTodo.empty(),
+ "Can't delete binder w/ pending async transactions");
+ mNodeForAddress.erase(it);
+ }
+ }
+
+ return ref;
+}
+
+bool RpcState::nodeProgressAsyncNumber(BinderNode* node, std::unique_lock<std::mutex>& lock) {
+ // 2**64 =~ 10**19 =~ 1000 transactions per second for 585 million years to
+ // a single binder
+ if (node->asyncNumber >= std::numeric_limits<decltype(node->asyncNumber)>::max()) {
+ ALOGE("Out of async transaction IDs. Terminating");
+ terminate(lock);
+ return false;
+ }
+ node->asyncNumber++;
+ return true;
+}
+
} // namespace android
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
index d63c1c3..81ff458 100644
--- a/libs/binder/RpcState.h
+++ b/libs/binder/RpcState.h
@@ -66,8 +66,15 @@
const sp<RpcSession>& session, Parcel* reply,
uint32_t flags);
[[nodiscard]] status_t sendDecStrong(const base::unique_fd& fd, const RpcAddress& address);
+
+ enum class CommandType {
+ ANY,
+ CONTROL_ONLY,
+ };
[[nodiscard]] status_t getAndExecuteCommand(const base::unique_fd& fd,
- const sp<RpcSession>& session);
+ const sp<RpcSession>& session, CommandType type);
+ [[nodiscard]] status_t drainCommands(const base::unique_fd& fd, const sp<RpcSession>& session,
+ CommandType type);
/**
* Called by Parcel for outgoing binders. This implies one refcount of
@@ -106,6 +113,9 @@
void terminate();
private:
+ void dumpLocked();
+ void terminate(std::unique_lock<std::mutex>& lock);
+
// Alternative to std::vector<uint8_t> that doesn't abort on allocation failure and caps
// large allocations to avoid being requested from allocating too much data.
struct CommandData {
@@ -129,7 +139,7 @@
Parcel* reply);
[[nodiscard]] status_t processServerCommand(const base::unique_fd& fd,
const sp<RpcSession>& session,
- const RpcWireHeader& command);
+ const RpcWireHeader& command, CommandType type);
[[nodiscard]] status_t processTransact(const base::unique_fd& fd, const sp<RpcSession>& session,
const RpcWireHeader& command);
[[nodiscard]] status_t processTransactInternal(const base::unique_fd& fd,
@@ -188,6 +198,16 @@
// (no additional data specific to remote binders)
};
+ // checks if there is any reference left to a node and erases it. If erase
+ // happens, and there is a strong reference to the binder kept by
+ // binderNode, this returns that strong reference, so that it can be
+ // dropped after any locks are removed.
+ sp<IBinder> tryEraseNode(std::map<RpcAddress, BinderNode>::iterator& it);
+ // true - success
+ // false - state terminated, lock gone, halt
+ [[nodiscard]] bool nodeProgressAsyncNumber(BinderNode* node,
+ std::unique_lock<std::mutex>& lock);
+
std::mutex mNodeMutex;
bool mTerminated = false;
// binders known by both sides of a session
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 601ce96..dac3819 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -33,7 +33,6 @@
Stability::Category Stability::Category::currentFromLevel(Level level) {
return {
.version = kBinderWireFormatVersion,
- .reserved = {0},
.level = level,
};
}
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 754f87c..d162dda 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -94,6 +94,13 @@
pid_t getDebugPid();
+ // Whether this binder has been sent to another process.
+ bool wasParceled();
+ // Consider this binder as parceled (setup/init-related calls should no
+ // longer by called. This is automatically set by when this binder is sent
+ // to another process.
+ void setParceled();
+
[[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd clientFd,
uint32_t maxRpcThreads);
@@ -119,10 +126,13 @@
std::atomic<Extras*> mExtras;
friend ::android::internal::Stability;
- union {
- int32_t mStability;
- void* mReserved0;
- };
+ int16_t mStability;
+ bool mParceled;
+ uint8_t mReserved0;
+
+#ifdef __LP64__
+ int32_t mReserved1;
+#endif
};
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 0082ec3..98db221 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -160,7 +160,6 @@
static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd);
bool setupSocketServer(const RpcSocketAddress& address);
- [[nodiscard]] bool acceptOne();
bool mAgreedExperimental = false;
size_t mMaxThreads = 1;
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 6bc607f..629b565 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -136,14 +136,15 @@
VINTF = 0b111111,
};
- // This is the format of stability passed on the wire.
+ // This is the format of stability passed on the wire. It is only 2 bytes
+ // long, but 2 bytes in addition to this are reserved here. The difference
+ // in size is in order to free up space in BBinder, which is fixed by
+ // prebuilts inheriting from it.
struct Category {
- static inline Category fromRepr(int32_t representation) {
+ static inline Category fromRepr(int16_t representation) {
return *reinterpret_cast<Category*>(&representation);
}
- int32_t repr() const {
- return *reinterpret_cast<const int32_t*>(this);
- }
+ int16_t repr() const { return *reinterpret_cast<const int16_t*>(this); }
static inline Category currentFromLevel(Level level);
bool operator== (const Category& o) const {
@@ -161,12 +162,10 @@
// class must write parcels according to the version documented here.
uint8_t version;
- uint8_t reserved[2];
-
// bitmask of Stability::Level
Level level;
};
- static_assert(sizeof(Category) == sizeof(int32_t));
+ static_assert(sizeof(Category) == sizeof(int16_t));
// returns the stability according to how this was built
static Level getLocalLevel();
diff --git a/libs/binder/libbinder.map b/libs/binder/libbinder.map
new file mode 100644
index 0000000..9ca14bc
--- /dev/null
+++ b/libs/binder/libbinder.map
@@ -0,0 +1,5 @@
+# b/190148312: Populate with correct list of ABI symbols
+LIBBINDER {
+ global:
+ *;
+};
diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp
index bb51bf0..ede4873 100644
--- a/libs/binder/ndk/tests/Android.bp
+++ b/libs/binder/ndk/tests/Android.bp
@@ -95,7 +95,7 @@
"libbinder_ndk",
"libutils",
],
- test_suites: ["general-tests", "vts"],
+ test_suites: ["general-tests"],
require_root: true,
}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 3289b5f..c4eacfd 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -29,6 +29,7 @@
#include <gtest/gtest.h>
#include <android-base/properties.h>
+#include <android-base/result-gmock.h>
#include <android-base/result.h>
#include <android-base/unique_fd.h>
#include <binder/Binder.h>
@@ -52,6 +53,7 @@
using namespace android;
using namespace std::string_literals;
using namespace std::chrono_literals;
+using android::base::testing::HasValue;
using testing::ExplainMatchResult;
using testing::Not;
using testing::WithParamInterface;
@@ -62,15 +64,6 @@
return expected == arg;
}
-// e.g. Result<int32_t> v = 0; EXPECT_THAT(result, ResultHasValue(0));
-MATCHER_P(ResultHasValue, resultMatcher, "") {
- if (!arg.ok()) {
- *result_listener << "contains error " << arg.error();
- return false;
- }
- return ExplainMatchResult(resultMatcher, arg.value(), result_listener);
-}
-
static ::testing::AssertionResult IsPageAligned(void *buf) {
if (((unsigned long)buf & ((unsigned long)PAGE_SIZE - 1)) == 0)
return ::testing::AssertionSuccess();
@@ -443,6 +436,14 @@
};
};
+TEST_F(BinderLibTest, WasParceled) {
+ auto binder = sp<BBinder>::make();
+ EXPECT_FALSE(binder->wasParceled());
+ Parcel data;
+ data.writeStrongBinder(binder);
+ EXPECT_TRUE(binder->wasParceled());
+}
+
TEST_F(BinderLibTest, NopTransaction) {
Parcel data, reply;
EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply),
@@ -514,7 +515,7 @@
}
TEST_F(BinderLibTest, GetId) {
- EXPECT_THAT(GetId(m_server), ResultHasValue(0));
+ EXPECT_THAT(GetId(m_server), HasValue(0));
}
TEST_F(BinderLibTest, PtrSize) {
@@ -1279,7 +1280,7 @@
sp<IBinder> server = isRemote ? sp<IBinder>(CreateRemoteService(id))
: sp<IBinder>(sp<BinderLibTestService>::make(id, false));
ASSERT_EQ(isRemote, !!server->remoteBinder());
- ASSERT_THAT(GetId(server), ResultHasValue(id));
+ ASSERT_THAT(GetId(server), HasValue(id));
unsigned int port = 0;
// Fake servicedispatcher.
@@ -1309,7 +1310,7 @@
EXPECT_EQ(OK, rpcServerBinder->pingBinder());
// Check that |rpcServerBinder| and |server| points to the same service.
- EXPECT_THAT(GetId(rpcServerBinder), ResultHasValue(id));
+ EXPECT_THAT(GetId(rpcServerBinder), HasValue(id));
// Occupy the server thread. The server should still have enough threads to handle
// other connections.
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index e48b7c5..0a970fb 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -876,7 +876,7 @@
TEST_P(BinderRpc, OnewayStressTest) {
constexpr size_t kNumClientThreads = 10;
constexpr size_t kNumServerThreads = 10;
- constexpr size_t kNumCalls = 50;
+ constexpr size_t kNumCalls = 500;
auto proc = createRpcTestSocketServerProcess(kNumServerThreads);
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index fd1793b..90532ec 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -208,6 +208,7 @@
case ANATIVEWINDOW_QUERY_DEFAULT_WIDTH:
case ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT:
case ANATIVEWINDOW_QUERY_TRANSFORM_HINT:
+ case ANATIVEWINDOW_QUERY_BUFFER_AGE:
// these are part of the VNDK API
break;
case ANATIVEWINDOW_QUERY_MIN_SWAP_INTERVAL: