Merge changes I118d5c8d,I9c3728cd
* changes:
libbinder_random_parcel: rand binder returns data
libbinder_random_parcel: splitout random binder
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 6fb9a4d..48d48ac 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -193,8 +193,9 @@
{ OPT, "events/ext4/ext4_da_write_end/enable" },
{ OPT, "events/ext4/ext4_sync_file_enter/enable" },
{ OPT, "events/ext4/ext4_sync_file_exit/enable" },
- { REQ, "events/block/block_rq_issue/enable" },
- { REQ, "events/block/block_rq_complete/enable" },
+ { OPT, "events/block/block_bio_queue/enable" },
+ { OPT, "events/block/block_bio_complete/enable" },
+ { OPT, "events/ufs/ufshcd_command/enable" },
} },
{ "mmc", "eMMC commands", 0, {
{ REQ, "events/mmc/enable" },
diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp
index 15bd5c3..ebc74fb 100644
--- a/libs/adbd_auth/adbd_auth.cpp
+++ b/libs/adbd_auth/adbd_auth.cpp
@@ -23,8 +23,10 @@
#include <sys/eventfd.h>
#include <sys/uio.h>
+#include <atomic>
#include <chrono>
#include <deque>
+#include <optional>
#include <string>
#include <string_view>
#include <tuple>
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 481d704..5e725a9 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -232,7 +232,10 @@
: mRpcServer(rpcServer), mKeepAliveBinder(keepAliveBinder), mBinder(binder) {}
virtual ~RpcServerLink();
void binderDied(const wp<IBinder>&) override {
- LOG_RPC_DETAIL("RpcServerLink: binder died, shutting down RpcServer");
+ auto promoted = mBinder.promote();
+ ALOGI("RpcBinder: binder died, shutting down RpcServer for %s",
+ promoted ? String8(promoted->getInterfaceDescriptor()).c_str() : "<NULL>");
+
if (mRpcServer == nullptr) {
ALOGW("RpcServerLink: Unable to shut down RpcServer because it does not exist.");
} else {
@@ -241,11 +244,7 @@
}
mRpcServer.clear();
- auto promoted = mBinder.promote();
- if (promoted == nullptr) {
- ALOGW("RpcServerLink: Unable to remove link from parent binder object because parent "
- "binder object is gone.");
- } else {
+ if (promoted) {
promoted->removeRpcServerLink(sp<RpcServerLink>::fromExisting(this));
}
mBinder.clear();
@@ -706,6 +705,7 @@
return status;
}
rpcServer->setMaxThreads(binderThreadPoolMaxCount);
+ LOG(INFO) << "RpcBinder: Started Binder debug on " << getInterfaceDescriptor();
rpcServer->start();
e->mRpcServerLinks.emplace(link);
LOG_RPC_DETAIL("%s(fd=%d) successful", __PRETTY_FUNCTION__, socketFdForPrint);
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index c411f4f..7067328 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -886,6 +886,7 @@
it->second.asyncTodo.push(BinderNode::AsyncTodo{
.ref = target,
.data = std::move(transactionData),
+ .ancillaryFds = std::move(ancillaryFds),
.asyncNumber = transaction->asyncNumber,
});
@@ -1046,6 +1047,7 @@
// reset up arguments
transactionData = std::move(todo.data);
+ ancillaryFds = std::move(todo.ancillaryFds);
LOG_ALWAYS_FATAL_IF(target != todo.ref,
"async list should be associated with a binder");
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
index 7aab5ee..ac86585 100644
--- a/libs/binder/RpcState.h
+++ b/libs/binder/RpcState.h
@@ -250,6 +250,7 @@
struct AsyncTodo {
sp<IBinder> ref;
CommandData data;
+ std::vector<std::variant<base::unique_fd, base::borrowed_fd>> ancillaryFds;
uint64_t asyncNumber = 0;
bool operator<(const AsyncTodo& o) const {
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index 7ea9be7..fccc0af 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -349,7 +349,7 @@
/**
* See AIBinder_Weak_promote.
*/
- SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); }
+ SpAIBinder promote() const { return SpAIBinder(AIBinder_Weak_promote(get())); }
};
namespace internal {
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 6d29238..01b9472 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -670,6 +670,26 @@
EXPECT_EQ(42, pparcel->readInt32());
}
+TEST(NdkBinder, GetAndVerifyScopedAIBinder_Weak) {
+ for (const ndk::SpAIBinder& binder :
+ {// remote
+ ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
+ // local
+ ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
+ // get a const ScopedAIBinder_Weak and verify promote
+ EXPECT_NE(binder.get(), nullptr);
+ const ndk::ScopedAIBinder_Weak wkAIBinder =
+ ndk::ScopedAIBinder_Weak(AIBinder_Weak_new(binder.get()));
+ EXPECT_EQ(wkAIBinder.promote().get(), binder.get());
+ // get another ScopedAIBinder_Weak and verify
+ ndk::ScopedAIBinder_Weak wkAIBinder2 =
+ ndk::ScopedAIBinder_Weak(AIBinder_Weak_new(binder.get()));
+ EXPECT_FALSE(AIBinder_Weak_lt(wkAIBinder.get(), wkAIBinder2.get()));
+ EXPECT_FALSE(AIBinder_Weak_lt(wkAIBinder2.get(), wkAIBinder.get()));
+ EXPECT_EQ(wkAIBinder2.promote(), wkAIBinder.promote());
+ }
+}
+
class MyResultReceiver : public BnResultReceiver {
public:
Mutex mMutex;
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
index b15a225..a3ed571 100644
--- a/libs/binder/tests/IBinderRpcTest.aidl
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -71,4 +71,13 @@
ParcelFileDescriptor echoAsFile(@utf8InCpp String content);
ParcelFileDescriptor concatFiles(in List<ParcelFileDescriptor> files);
+
+ // FDs sent via `blockingSendFdOneway` can be received via
+ // `blockingRecvFd`. The handler for `blockingSendFdOneway` will block
+ // until the next `blockingRecvFd` call.
+ //
+ // This is useful for carefully controlling how/when oneway transactions
+ // get queued.
+ oneway void blockingSendFdOneway(in ParcelFileDescriptor fd);
+ ParcelFileDescriptor blockingRecvFd();
}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 6e1c8ac..25b524f 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -115,6 +115,7 @@
BINDER_LIB_TEST_NOP_TRANSACTION_WAIT,
BINDER_LIB_TEST_GETPID,
BINDER_LIB_TEST_ECHO_VECTOR,
+ BINDER_LIB_TEST_GET_NON_BLOCKING_FD,
BINDER_LIB_TEST_REJECT_OBJECTS,
BINDER_LIB_TEST_CAN_GET_SID,
BINDER_LIB_TEST_GET_MAX_THREAD_COUNT,
@@ -1158,6 +1159,21 @@
EXPECT_EQ(readValue, testValue);
}
+TEST_F(BinderLibTest, FileDescriptorRemainsNonBlocking) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+
+ Parcel reply;
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_NON_BLOCKING_FD, {} /*data*/, &reply),
+ StatusEq(NO_ERROR));
+ base::unique_fd fd;
+ EXPECT_THAT(reply.readUniqueFileDescriptor(&fd), StatusEq(OK));
+
+ const int result = fcntl(fd.get(), F_GETFL);
+ ASSERT_NE(result, -1);
+ EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK);
+}
+
// see ProcessState.cpp BINDER_VM_SIZE = 1MB.
// This value is not exposed, but some code in the framework relies on being able to use
// buffers near the cap size.
@@ -1801,6 +1817,28 @@
reply->writeUint64Vector(vector);
return NO_ERROR;
}
+ case BINDER_LIB_TEST_GET_NON_BLOCKING_FD: {
+ std::array<int, 2> sockets;
+ const bool created = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets.data()) == 0;
+ if (!created) {
+ ALOGE("Could not create socket pair");
+ return UNKNOWN_ERROR;
+ }
+
+ const int result = fcntl(sockets[0], F_SETFL, O_NONBLOCK);
+ if (result != 0) {
+ ALOGE("Could not make socket non-blocking: %s", strerror(errno));
+ return UNKNOWN_ERROR;
+ }
+ base::unique_fd out(sockets[0]);
+ status_t writeResult = reply->writeUniqueFileDescriptor(out);
+ if (writeResult != NO_ERROR) {
+ ALOGE("Could not write unique_fd");
+ return writeResult;
+ }
+ close(sockets[1]); // we don't need the other side of the fd
+ return NO_ERROR;
+ }
case BINDER_LIB_TEST_REJECT_OBJECTS: {
return data.objectsCount() == 0 ? BAD_VALUE : NO_ERROR;
}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 9a6d4df..2b70492 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -181,8 +181,10 @@
wp<RpcSession> weakSession = session;
session = nullptr;
- EXPECT_EQ(nullptr, weakSession.promote())
- << (debugBacktrace(host.getPid()), debugBacktrace(getpid()), "Leaked session");
+ sp<RpcSession> strongSession = weakSession.promote();
+ EXPECT_EQ(nullptr, strongSession)
+ << (debugBacktrace(host.getPid()), debugBacktrace(getpid()), "Leaked sess: ")
+ << strongSession->getStrongCount();
}
}
};
@@ -786,12 +788,12 @@
ts.push_back(std::thread([&] { proc.rootIface->lockUnlock(); }));
}
- usleep(100000); // give chance for calls on other threads
+ usleep(10000); // give chance for calls on other threads
// other calls still work
EXPECT_EQ(OK, proc.rootBinder->pingBinder());
- constexpr size_t blockTimeMs = 500;
+ constexpr size_t blockTimeMs = 50;
size_t epochMsBefore = epochMillis();
// after this, we should never see a response within this time
EXPECT_OK(proc.rootIface->unlockInMsAsync(blockTimeMs));
@@ -920,6 +922,45 @@
EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs);
}
+TEST_P(BinderRpc, OnewayCallQueueingWithFds) {
+ if (!supportsFdTransport()) {
+ GTEST_SKIP() << "Would fail trivially (which is tested elsewhere)";
+ }
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
+ // This test forces a oneway transaction to be queued by issuing two
+ // `blockingSendFdOneway` calls, then drains the queue by issuing two
+ // `blockingRecvFd` calls.
+ //
+ // For more details about the queuing semantics see
+ // https://developer.android.com/reference/android/os/IBinder#FLAG_ONEWAY
+
+ auto proc = createRpcTestSocketServerProcess({
+ .numThreads = 3,
+ .clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX,
+ .serverSupportedFileDescriptorTransportModes =
+ {RpcSession::FileDescriptorTransportMode::UNIX},
+ });
+
+ EXPECT_OK(proc.rootIface->blockingSendFdOneway(
+ android::os::ParcelFileDescriptor(mockFileDescriptor("a"))));
+ EXPECT_OK(proc.rootIface->blockingSendFdOneway(
+ android::os::ParcelFileDescriptor(mockFileDescriptor("b"))));
+
+ android::os::ParcelFileDescriptor fdA;
+ EXPECT_OK(proc.rootIface->blockingRecvFd(&fdA));
+ std::string result;
+ CHECK(android::base::ReadFdToString(fdA.get(), &result));
+ EXPECT_EQ(result, "a");
+
+ android::os::ParcelFileDescriptor fdB;
+ EXPECT_OK(proc.rootIface->blockingRecvFd(&fdB));
+ CHECK(android::base::ReadFdToString(fdB.get(), &result));
+ EXPECT_EQ(result, "b");
+}
+
TEST_P(BinderRpc, OnewayCallQueueing) {
if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
@@ -1083,7 +1124,7 @@
}
std::unique_lock<std::mutex> lock(dr->mMtx);
- ASSERT_TRUE(dr->mCv.wait_for(lock, 1000ms, [&]() { return dr->dead; }));
+ ASSERT_TRUE(dr->mCv.wait_for(lock, 100ms, [&]() { return dr->dead; }));
// need to wait for the session to shutdown so we don't "Leak session"
EXPECT_TRUE(proc.proc.sessions.at(0).session->shutdownAndWait(true));
@@ -1118,7 +1159,7 @@
std::unique_lock<std::mutex> lock(dr->mMtx);
if (!dr->dead) {
- EXPECT_EQ(std::cv_status::no_timeout, dr->mCv.wait_for(lock, 1000ms));
+ EXPECT_EQ(std::cv_status::no_timeout, dr->mCv.wait_for(lock, 100ms));
}
EXPECT_TRUE(dr->dead) << "Failed to receive the death notification.";
@@ -1701,7 +1742,7 @@
bool shutdown = false;
for (int i = 0; i < 10 && !shutdown; i++) {
- usleep(300 * 1000); // 300ms; total 3s
+ usleep(30 * 1000); // 30ms; total 300ms
if (server->shutdown()) shutdown = true;
}
ASSERT_TRUE(shutdown) << "server->shutdown() never returns true";
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index 4513d36..fddf5f3 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -167,6 +167,42 @@
return readFd;
}
+// A threadsafe channel where writes block until the value is read.
+template <typename T>
+class HandoffChannel {
+public:
+ void write(T v) {
+ {
+ RpcMutexUniqueLock lock(mMutex);
+ // Wait for space to send.
+ mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
+ mValue.emplace(std::move(v));
+ }
+ mCvFull.notify_all();
+ RpcMutexUniqueLock lock(mMutex);
+ // Wait for it to be taken.
+ mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
+ }
+
+ T read() {
+ RpcMutexUniqueLock lock(mMutex);
+ if (!mValue.has_value()) {
+ mCvFull.wait(lock, [&]() { return mValue.has_value(); });
+ }
+ T v = std::move(mValue.value());
+ mValue.reset();
+ lock.unlock();
+ mCvEmpty.notify_all();
+ return std::move(v);
+ }
+
+private:
+ RpcMutex mMutex;
+ RpcConditionVariable mCvEmpty;
+ RpcConditionVariable mCvFull;
+ std::optional<T> mValue;
+};
+
using android::binder::Status;
class MyBinderRpcSession : public BnBinderRpcSession {
@@ -374,6 +410,18 @@
out->reset(mockFileDescriptor(acc));
return Status::ok();
}
+
+ HandoffChannel<android::base::unique_fd> mFdChannel;
+
+ Status blockingSendFdOneway(const android::os::ParcelFileDescriptor& fd) override {
+ mFdChannel.write(android::base::unique_fd(fcntl(fd.get(), F_DUPFD_CLOEXEC, 0)));
+ return Status::ok();
+ }
+
+ Status blockingRecvFd(android::os::ParcelFileDescriptor* fd) override {
+ fd->reset(mFdChannel.read());
+ return Status::ok();
+ }
};
} // namespace android
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 1fe8800..6af2cc1 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -668,10 +668,11 @@
// VkSurfaceProtectedCapabilitiesKHR::supportsProtected. The following
// four values cannot be known without a surface. Default values will
// be supplied anyway, but cannot be relied upon.
- width = 1000;
- height = 1000;
- transform_hint = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- max_buffer_count = 10;
+ width = 0xFFFFFFFF;
+ height = 0xFFFFFFFF;
+ transform_hint = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
+ capabilities->minImageCount = 0xFFFFFFFF;
+ capabilities->maxImageCount = 0xFFFFFFFF;
} else {
ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
@@ -703,9 +704,9 @@
strerror(-err), err);
return VK_ERROR_SURFACE_LOST_KHR;
}
+ capabilities->minImageCount = std::min(max_buffer_count, 3);
+ capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
}
- capabilities->minImageCount = std::min(max_buffer_count, 3);
- capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
capabilities->currentExtent =
VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};