diff options
Diffstat (limited to 'libs')
33 files changed, 368 insertions, 118 deletions
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index bb1b5138e0..2ecb8951d7 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -153,10 +153,6 @@ cc_library { export_aidl_headers: true, }, - // TODO(b/142684679): for com.android.media which is compiled - // as vendor and used as system code. - use_apex_name_macro: true, - cflags: [ "-Wall", "-Wextra", diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index d3eef4e88e..ec9d5544f9 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -547,7 +547,6 @@ status_t BBinder::setRpcClientDebug(android::base::unique_fd socketFd, AutoMutex _l(e->mLock); auto rpcServer = RpcServer::make(); LOG_ALWAYS_FATAL_IF(rpcServer == nullptr, "RpcServer::make returns null"); - rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); auto link = sp<RpcServerLink>::make(rpcServer, keepAliveBinder, weakThis); if (auto status = keepAliveBinder->linkToDeath(link, nullptr, 0); status != OK) { ALOGE("%s: keepAliveBinder->linkToDeath returns %s", __PRETTY_FUNCTION__, diff --git a/libs/binder/OWNERS b/libs/binder/OWNERS index 350994a86b..1c8bdea27d 100644 --- a/libs/binder/OWNERS +++ b/libs/binder/OWNERS @@ -1,5 +1,7 @@ +# Bug component: 32456 arve@google.com ctate@google.com hackbod@google.com maco@google.com smoreland@google.com +tkjos@google.com diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index dee5309602..181f4051b7 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -411,8 +411,9 @@ status_t Parcel::setData(const uint8_t* buffer, size_t len) status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len) { - if (parcel->isForRpc() != isForRpc()) { - ALOGE("Cannot append Parcel of one format to another."); + if (mSession != parcel->mSession) { + ALOGE("Cannot append Parcel from one context to another. They may be different formats, " + "and objects are specific to a context."); return BAD_TYPE; } @@ -547,21 +548,17 @@ bool Parcel::hasFileDescriptors() const return mHasFds; } -status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool& result) const { +status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool* result) const { if (len > INT32_MAX || offset > INT32_MAX) { // Don't accept size_t values which may have come from an inadvertent conversion from a // negative int. return BAD_VALUE; } - size_t limit = offset + len; - if (offset > mDataSize || len > mDataSize || limit > mDataSize || offset > limit) { + size_t limit; + if (__builtin_add_overflow(offset, len, &limit) || limit > mDataSize) { return BAD_VALUE; } - result = hasFileDescriptorsInRangeUnchecked(offset, len); - return NO_ERROR; -} - -bool Parcel::hasFileDescriptorsInRangeUnchecked(size_t offset, size_t len) const { + *result = false; for (size_t i = 0; i < mObjectsSize; i++) { size_t pos = mObjects[i]; if (pos < offset) continue; @@ -571,10 +568,11 @@ bool Parcel::hasFileDescriptorsInRangeUnchecked(size_t offset, size_t len) const } const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + pos); if (flat->hdr.type == BINDER_TYPE_FD) { - return true; + *result = true; + break; } } - return false; + return NO_ERROR; } void Parcel::markSensitive() const @@ -2567,9 +2565,9 @@ void Parcel::initState() } } -void Parcel::scanForFds() const -{ - mHasFds = hasFileDescriptorsInRangeUnchecked(0, dataSize()); +void Parcel::scanForFds() const { + status_t status = hasFileDescriptorsInRange(0, dataSize(), &mHasFds); + ALOGE_IF(status != NO_ERROR, "Error %d calling hasFileDescriptorsInRange()", status); mFdsKnown = true; } diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 94b28063ab..4f21cda4a1 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -89,13 +89,21 @@ sp<ProcessState> ProcessState::selfOrNull() return init(nullptr, false /*requireDefault*/); } +[[clang::no_destroy]] static sp<ProcessState> gProcess; +[[clang::no_destroy]] static std::mutex gProcessMutex; + +static void verifyNotForked(bool forked) { + LOG_ALWAYS_FATAL_IF(forked, "libbinder ProcessState can not be used after fork"); +} + sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault) { - [[clang::no_destroy]] static sp<ProcessState> gProcess; - [[clang::no_destroy]] static std::mutex gProcessMutex; if (driver == nullptr) { std::lock_guard<std::mutex> l(gProcessMutex); + if (gProcess) { + verifyNotForked(gProcess->mForked); + } return gProcess; } @@ -106,6 +114,14 @@ sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault) driver = "/dev/binder"; } + // we must install these before instantiating the gProcess object, + // otherwise this would race with creating it, and there could be the + // possibility of an invalid gProcess object forked by another thread + // before these are installed + int ret = pthread_atfork(ProcessState::onFork, ProcessState::parentPostFork, + ProcessState::childPostFork); + LOG_ALWAYS_FATAL_IF(ret != 0, "pthread_atfork error %s", strerror(ret)); + std::lock_guard<std::mutex> l(gProcessMutex); gProcess = sp<ProcessState>::make(driver); }); @@ -119,6 +135,7 @@ sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault) gProcess->getDriverName().c_str(), driver); } + verifyNotForked(gProcess->mForked); return gProcess; } @@ -137,6 +154,24 @@ sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/) return context; } +void ProcessState::onFork() { + // make sure another thread isn't currently retrieving ProcessState + gProcessMutex.lock(); +} + +void ProcessState::parentPostFork() { + gProcessMutex.unlock(); +} + +void ProcessState::childPostFork() { + // another thread might call fork before gProcess is instantiated, but after + // the thread handler is installed + if (gProcess) { + gProcess->mForked = true; + } + gProcessMutex.unlock(); +} + void ProcessState::startThreadPool() { AutoMutex _l(mLock); @@ -426,6 +461,7 @@ ProcessState::ProcessState(const char* driver) mWaitingForThreads(0), mMaxThreads(DEFAULT_MAX_BINDER_THREADS), mStarvationStartTimeMs(0), + mForked(false), mThreadPoolStarted(false), mThreadPoolSeq(1), mCallRestriction(CallRestriction::NONE) { diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index 967b8e3801..93ed50e986 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -58,10 +58,6 @@ sp<RpcServer> RpcServer::make(std::unique_ptr<RpcTransportCtxFactory> rpcTranspo return sp<RpcServer>::make(std::move(ctx)); } -void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() { - mAgreedExperimental = true; -} - status_t RpcServer::setupUnixDomainServer(const char* path) { return setupSocketServer(UnixSocketAddress(path)); } @@ -127,14 +123,23 @@ void RpcServer::setProtocolVersion(uint32_t version) { void RpcServer::setRootObject(const sp<IBinder>& binder) { std::lock_guard<std::mutex> _l(mLock); + mRootObjectFactory = nullptr; mRootObjectWeak = mRootObject = binder; } void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) { std::lock_guard<std::mutex> _l(mLock); mRootObject.clear(); + mRootObjectFactory = nullptr; mRootObjectWeak = binder; } +void RpcServer::setPerSessionRootObject( + std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& makeObject) { + std::lock_guard<std::mutex> _l(mLock); + mRootObject.clear(); + mRootObjectWeak.clear(); + mRootObjectFactory = std::move(makeObject); +} sp<IBinder> RpcServer::getRootObject() { std::lock_guard<std::mutex> _l(mLock); @@ -154,14 +159,12 @@ static void joinRpcServer(sp<RpcServer>&& thiz) { } void RpcServer::start() { - LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); std::lock_guard<std::mutex> _l(mLock); LOG_ALWAYS_FATAL_IF(mJoinThread.get(), "Already started!"); mJoinThread = std::make_unique<std::thread>(&joinRpcServer, sp<RpcServer>::fromExisting(this)); } void RpcServer::join() { - LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); { std::lock_guard<std::mutex> _l(mLock); @@ -174,8 +177,14 @@ void RpcServer::join() { status_t status; while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) { - unique_fd clientFd(TEMP_FAILURE_RETRY( - accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC | SOCK_NONBLOCK))); + sockaddr_storage addr; + socklen_t addrLen = sizeof(addr); + + unique_fd clientFd( + TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(&addr), + &addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK))); + + LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(addr)), "Truncated address"); if (clientFd < 0) { ALOGE("Could not accept4 socket: %s", strerror(errno)); @@ -187,7 +196,7 @@ void RpcServer::join() { std::lock_guard<std::mutex> _l(mLock); std::thread thread = std::thread(&RpcServer::establishConnection, sp<RpcServer>::fromExisting(this), - std::move(clientFd)); + std::move(clientFd), addr, addrLen); mConnectingThreads[thread.get_id()] = std::move(thread); } } @@ -257,10 +266,8 @@ size_t RpcServer::numUninitializedSessions() { return mConnectingThreads.size(); } -void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd) { - // TODO(b/183988761): cannot trust this simple ID - LOG_ALWAYS_FATAL_IF(!server->mAgreedExperimental, "no!"); - +void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd, + const sockaddr_storage addr, socklen_t addrLen) { // mShutdownTrigger can only be cleared once connection threads have joined. // It must be set before this thread is started LOG_ALWAYS_FATAL_IF(server->mShutdownTrigger == nullptr); @@ -383,11 +390,23 @@ void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clie session = RpcSession::make(); session->setMaxIncomingThreads(server->mMaxThreads); if (!session->setProtocolVersion(protocolVersion)) return; + + // if null, falls back to server root + sp<IBinder> sessionSpecificRoot; + if (server->mRootObjectFactory != nullptr) { + sessionSpecificRoot = + server->mRootObjectFactory(reinterpret_cast<const sockaddr*>(&addr), + addrLen); + if (sessionSpecificRoot == nullptr) { + ALOGE("Warning: server returned null from root object factory"); + } + } + if (!session->setForServer(server, sp<RpcServer::EventListener>::fromExisting( static_cast<RpcServer::EventListener*>( server.get())), - sessionId)) { + sessionId, sessionSpecificRoot)) { ALOGE("Failed to attach server to session"); return; } @@ -478,19 +497,16 @@ void RpcServer::onSessionIncomingThreadEnded() { } bool RpcServer::hasServer() { - LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); std::lock_guard<std::mutex> _l(mLock); return mServer.ok(); } unique_fd RpcServer::releaseServer() { - LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); std::lock_guard<std::mutex> _l(mLock); return std::move(mServer); } status_t RpcServer::setupExternalServer(base::unique_fd serverFd) { - LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); std::lock_guard<std::mutex> _l(mLock); if (mServer.ok()) { ALOGE("Each RpcServer can only have one server."); diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp index 9eef3e8914..137411bc6b 100644 --- a/libs/binder/RpcSession.cpp +++ b/libs/binder/RpcSession.cpp @@ -700,7 +700,8 @@ status_t RpcSession::addOutgoingConnection(std::unique_ptr<RpcTransport> rpcTran } bool RpcSession::setForServer(const wp<RpcServer>& server, const wp<EventListener>& eventListener, - const std::vector<uint8_t>& sessionId) { + const std::vector<uint8_t>& sessionId, + const sp<IBinder>& sessionSpecificRoot) { LOG_ALWAYS_FATAL_IF(mForServer != nullptr); LOG_ALWAYS_FATAL_IF(server == nullptr); LOG_ALWAYS_FATAL_IF(mEventListener != nullptr); @@ -713,6 +714,7 @@ bool RpcSession::setForServer(const wp<RpcServer>& server, const wp<EventListene mId = sessionId; mForServer = server; mEventListener = eventListener; + mSessionSpecificRootObject = sessionSpecificRoot; return true; } diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp index 9ba64f3407..09b3d68626 100644 --- a/libs/binder/RpcState.cpp +++ b/libs/binder/RpcState.cpp @@ -870,7 +870,9 @@ processTransactInternalTailCall: if (server) { switch (transaction->code) { case RPC_SPECIAL_TRANSACT_GET_ROOT: { - replyStatus = reply.writeStrongBinder(server->getRootObject()); + sp<IBinder> root = session->mSessionSpecificRootObject + ?: server->getRootObject(); + replyStatus = reply.writeStrongBinder(root); break; } default: { diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index cf30f17015..d90e803668 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -87,7 +87,7 @@ public: void restoreAllowFds(bool lastValue); bool hasFileDescriptors() const; - status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool& result) const; + status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool* result) const; // Zeros data when reallocating. Other mitigations may be added // in the future. @@ -576,7 +576,6 @@ private: status_t writeRawNullableParcelable(const Parcelable* parcelable); - bool hasFileDescriptorsInRangeUnchecked(size_t offset, size_t length) const; //----------------------------------------------------------------------------- // Generic type read and write methods for Parcel: @@ -1237,7 +1236,9 @@ public: */ size_t getOpenAshmemSize() const; - // TODO(b/202029388): Remove 'getBlobAshmemSize' once ABI can be changed. +private: + // TODO(b/202029388): Remove 'getBlobAshmemSize' once no prebuilts reference + // this size_t getBlobAshmemSize() const; }; diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h index 72c2ab7b31..cf8d8e433c 100644 --- a/libs/binder/include/binder/ProcessState.h +++ b/libs/binder/include/binder/ProcessState.h @@ -94,6 +94,10 @@ public: private: static sp<ProcessState> init(const char* defaultDriver, bool requireDefault); + static void onFork(); + static void parentPostFork(); + static void childPostFork(); + friend class IPCThreadState; friend class sp<ProcessState>; @@ -132,6 +136,7 @@ private: Vector<handle_entry> mHandleToObject; + bool mForked; bool mThreadPoolStarted; volatile int32_t mThreadPoolSeq; diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h index fb2cf23cd0..a4267137f4 100644 --- a/libs/binder/include/binder/RpcServer.h +++ b/libs/binder/include/binder/RpcServer.h @@ -25,10 +25,6 @@ #include <mutex> #include <thread> -// WARNING: This is a feature which is still in development, and it is subject -// to radical change. Any production use of this may subject your code to any -// number of problems. - namespace android { class FdTrigger; @@ -99,8 +95,6 @@ public: */ [[nodiscard]] status_t setupExternalServer(base::unique_fd serverFd); - void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); - /** * This must be called before adding a client session. * @@ -130,6 +124,10 @@ public: * Holds a weak reference to the root object. */ void setRootObjectWeak(const wp<IBinder>& binder); + /** + * Allows a root object to be created for each session + */ + void setPerSessionRootObject(std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& object); sp<IBinder> getRootObject(); /** @@ -179,11 +177,11 @@ private: void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override; void onSessionIncomingThreadEnded() override; - static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd); + static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd, + const sockaddr_storage addr, socklen_t addrLen); status_t setupSocketServer(const RpcSocketAddress& address); const std::unique_ptr<RpcTransportCtx> mCtx; - bool mAgreedExperimental = false; size_t mMaxThreads = 1; std::optional<uint32_t> mProtocolVersion; base::unique_fd mServer; // socket we are accepting sessions on @@ -194,6 +192,7 @@ private: std::map<std::thread::id, std::thread> mConnectingThreads; sp<IBinder> mRootObject; wp<IBinder> mRootObjectWeak; + std::function<sp<IBinder>(const sockaddr*, socklen_t)> mRootObjectFactory; std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions; std::unique_ptr<FdTrigger> mShutdownTrigger; std::condition_variable mShutdownCv; diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h index f5505da128..bd1063db90 100644 --- a/libs/binder/include/binder/RpcSession.h +++ b/libs/binder/include/binder/RpcSession.h @@ -26,10 +26,6 @@ #include <thread> #include <vector> -// WARNING: This is a feature which is still in development, and it is subject -// to radical change. Any production use of this may subject your code to any -// number of problems. - namespace android { class Parcel; @@ -256,7 +252,8 @@ private: bool init); [[nodiscard]] bool setForServer(const wp<RpcServer>& server, const wp<RpcSession::EventListener>& eventListener, - const std::vector<uint8_t>& sessionId); + const std::vector<uint8_t>& sessionId, + const sp<IBinder>& sessionSpecificRoot); sp<RpcConnection> assignIncomingConnectionToThisThread( std::unique_ptr<RpcTransport> rpcTransport); [[nodiscard]] bool removeIncomingConnection(const sp<RpcConnection>& connection); @@ -313,6 +310,10 @@ private: sp<WaitForShutdownListener> mShutdownListener; // used for client sessions wp<EventListener> mEventListener; // mForServer if server, mShutdownListener if client + // session-specific root object (if a different root is used for each + // session) + sp<IBinder> mSessionSpecificRootObject; + std::vector<uint8_t> mId; std::unique_ptr<FdTrigger> mShutdownTrigger; diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp index cad55fb439..6dfec75b2c 100644 --- a/libs/binder/libbinder_rpc_unstable.cpp +++ b/libs/binder/libbinder_rpc_unstable.cpp @@ -32,7 +32,6 @@ extern "C" { bool RunRpcServerCallback(AIBinder* service, unsigned int port, void (*readyCallback)(void* param), void* param) { auto server = RpcServer::make(); - server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); if (status_t status = server->setupVsockServer(port); status != OK) { LOG(ERROR) << "Failed to set up vsock server with port " << port << " error: " << statusToString(status).c_str(); diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp index 49c7b7cc08..81aa551dac 100644 --- a/libs/binder/ndk/ibinder.cpp +++ b/libs/binder/ndk/ibinder.cpp @@ -780,3 +780,7 @@ AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binde AIBinder_incStrong(ndkBinder.get()); return ndkBinder.get(); } + +void AIBinder_setMinSchedulerPolicy(AIBinder* binder, int policy, int priority) { + binder->asABBinder()->setMinSchedulerPolicy(policy, priority); +} diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h index 563d011adc..2b18a0a1e0 100644 --- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h +++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h @@ -543,6 +543,28 @@ binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, vo } /** + * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. + */ +template <typename P> +binder_status_t AParcel_writeNullableStdVectorParcelableElement(AParcel* parcel, + const void* vectorData, + size_t index) { + const std::optional<std::vector<P>>* vector = + static_cast<const std::optional<std::vector<P>>*>(vectorData); + return AParcel_writeNullableParcelable(parcel, (*vector)->at(index)); +} + +/** + * Reads a parcelable object of type P inside a std::vector<P> at index 'index' from 'parcel'. + */ +template <typename P> +binder_status_t AParcel_readNullableStdVectorParcelableElement(const AParcel* parcel, + void* vectorData, size_t index) { + std::optional<std::vector<P>>* vector = static_cast<std::optional<std::vector<P>>*>(vectorData); + return AParcel_readNullableParcelable(parcel, &(*vector)->at(index)); +} + +/** * Writes a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index' * to 'parcel'. */ @@ -551,11 +573,7 @@ inline binder_status_t AParcel_writeStdVectorParcelableElement<ScopedFileDescrip AParcel* parcel, const void* vectorData, size_t index) { const std::vector<ScopedFileDescriptor>* vector = static_cast<const std::vector<ScopedFileDescriptor>*>(vectorData); - int writeFd = vector->at(index).get(); - if (writeFd < 0) { - return STATUS_UNEXPECTED_NULL; - } - return AParcel_writeParcelFileDescriptor(parcel, writeFd); + return AParcel_writeRequiredParcelFileDescriptor(parcel, vector->at(index)); } /** @@ -567,15 +585,79 @@ inline binder_status_t AParcel_readStdVectorParcelableElement<ScopedFileDescript const AParcel* parcel, void* vectorData, size_t index) { std::vector<ScopedFileDescriptor>* vector = static_cast<std::vector<ScopedFileDescriptor>*>(vectorData); - int readFd; - binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd); - if (status == STATUS_OK) { - if (readFd < 0) { - return STATUS_UNEXPECTED_NULL; - } - vector->at(index).set(readFd); - } - return status; + return AParcel_readRequiredParcelFileDescriptor(parcel, &vector->at(index)); +} + +/** + * Writes a ScopedFileDescriptor object inside a std::optional<std::vector<ScopedFileDescriptor>> at + * index 'index' to 'parcel'. + */ +template <> +inline binder_status_t AParcel_writeNullableStdVectorParcelableElement<ScopedFileDescriptor>( + AParcel* parcel, const void* vectorData, size_t index) { + const std::optional<std::vector<ScopedFileDescriptor>>* vector = + static_cast<const std::optional<std::vector<ScopedFileDescriptor>>*>(vectorData); + return AParcel_writeNullableParcelFileDescriptor(parcel, (*vector)->at(index)); +} + +/** + * Reads a ScopedFileDescriptor object inside a std::optional<std::vector<ScopedFileDescriptor>> at + * index 'index' from 'parcel'. + */ +template <> +inline binder_status_t AParcel_readNullableStdVectorParcelableElement<ScopedFileDescriptor>( + const AParcel* parcel, void* vectorData, size_t index) { + std::optional<std::vector<ScopedFileDescriptor>>* vector = + static_cast<std::optional<std::vector<ScopedFileDescriptor>>*>(vectorData); + return AParcel_readNullableParcelFileDescriptor(parcel, &(*vector)->at(index)); +} + +/** + * Writes an SpAIBinder object inside a std::vector<SpAIBinder> at index 'index' + * to 'parcel'. + */ +template <> +inline binder_status_t AParcel_writeStdVectorParcelableElement<SpAIBinder>(AParcel* parcel, + const void* vectorData, + size_t index) { + const std::vector<SpAIBinder>* vector = static_cast<const std::vector<SpAIBinder>*>(vectorData); + return AParcel_writeRequiredStrongBinder(parcel, vector->at(index)); +} + +/** + * Reads an SpAIBinder object inside a std::vector<SpAIBinder> at index 'index' + * from 'parcel'. + */ +template <> +inline binder_status_t AParcel_readStdVectorParcelableElement<SpAIBinder>(const AParcel* parcel, + void* vectorData, + size_t index) { + std::vector<SpAIBinder>* vector = static_cast<std::vector<SpAIBinder>*>(vectorData); + return AParcel_readRequiredStrongBinder(parcel, &vector->at(index)); +} + +/** + * Writes an SpAIBinder object inside a std::optional<std::vector<SpAIBinder>> at index 'index' + * to 'parcel'. + */ +template <> +inline binder_status_t AParcel_writeNullableStdVectorParcelableElement<SpAIBinder>( + AParcel* parcel, const void* vectorData, size_t index) { + const std::optional<std::vector<SpAIBinder>>* vector = + static_cast<const std::optional<std::vector<SpAIBinder>>*>(vectorData); + return AParcel_writeNullableStrongBinder(parcel, (*vector)->at(index)); +} + +/** + * Reads an SpAIBinder object inside a std::optional<std::vector<SpAIBinder>> at index 'index' + * from 'parcel'. + */ +template <> +inline binder_status_t AParcel_readNullableStdVectorParcelableElement<SpAIBinder>( + const AParcel* parcel, void* vectorData, size_t index) { + std::optional<std::vector<SpAIBinder>>* vector = + static_cast<std::optional<std::vector<SpAIBinder>>*>(vectorData); + return AParcel_readNullableStrongBinder(parcel, &(*vector)->at(index)); } /** @@ -598,6 +680,30 @@ static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vec AParcel_readStdVectorParcelableElement<P>); } +/** + * Convenience API for writing a std::optional<std::vector<P>> + */ +template <typename P> +static inline binder_status_t AParcel_writeVector(AParcel* parcel, + const std::optional<std::vector<P>>& vec) { + if (!vec) return AParcel_writeInt32(parcel, -1); + const void* vectorData = static_cast<const void*>(&vec); + return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec->size()), + AParcel_writeNullableStdVectorParcelableElement<P>); +} + +/** + * Convenience API for reading a std::optional<std::vector<P>> + */ +template <typename P> +static inline binder_status_t AParcel_readVector(const AParcel* parcel, + std::optional<std::vector<P>>* vec) { + void* vectorData = static_cast<void*>(vec); + return AParcel_readParcelableArray(parcel, vectorData, + AParcel_nullableStdVectorExternalAllocator<P>, + AParcel_readNullableStdVectorParcelableElement<P>); +} + // @START /** * Writes a vector of int32_t to the next location in a non-null parcel. diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h index e315c798ee..b0217c4efc 100644 --- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h +++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h @@ -55,4 +55,17 @@ __attribute__((weak)) void AIBinder_setRequestingSid(AIBinder* binder, bool requ */ __attribute__((weak, warn_unused_result)) const char* AIBinder_getCallingSid() __INTRODUCED_IN(31); +/** + * Sets a minimum scheduler policy for all transactions coming into this + * AIBinder. + * + * This must be called before the object is sent to another process. + * Aborts on invalid values. Not thread safe. + * + * \param binder local server binder to set the policy for + * \param policy scheduler policy as defined in linux UAPI + * \param priority priority. [-20..19] for SCHED_NORMAL, [1..99] for RT + */ +void AIBinder_setMinSchedulerPolicy(AIBinder* binder, int policy, int priority) __INTRODUCED_IN(33); + __END_DECLS diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index 8605686740..64170af6fc 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -145,6 +145,7 @@ LIBBINDER_NDK33 { # introduced=33 global: AIBinder_Class_disableInterfaceTokenHeader; AIBinder_DeathRecipient_setOnUnlinked; + AIBinder_setMinSchedulerPolicy; # llndk AParcel_marshal; AParcel_unmarshal; }; diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs index f71a686959..8bcc5d0092 100644 --- a/libs/binder/rust/src/parcel/file_descriptor.rs +++ b/libs/binder/rust/src/parcel/file_descriptor.rs @@ -94,8 +94,6 @@ impl SerializeOption for ParcelFileDescriptor { } } -impl SerializeArray for Option<ParcelFileDescriptor> {} - impl DeserializeOption for ParcelFileDescriptor { fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { let mut fd = -1i32; @@ -126,8 +124,6 @@ impl DeserializeOption for ParcelFileDescriptor { } } -impl DeserializeArray for Option<ParcelFileDescriptor> {} - impl Deserialize for ParcelFileDescriptor { fn deserialize(parcel: &Parcel) -> Result<Self> { Deserialize::deserialize(parcel) diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs index 499ef09e6a..ec00e1dc86 100644 --- a/libs/binder/rust/src/parcel/parcelable.rs +++ b/libs/binder/rust/src/parcel/parcelable.rs @@ -383,6 +383,9 @@ macro_rules! impl_parcelable { }; } +impl<T: DeserializeOption> DeserializeArray for Option<T> {} +impl<T: SerializeOption> SerializeArray for Option<T> {} + parcelable_primitives! { impl Serialize for bool = sys::AParcel_writeBool; impl Deserialize for bool = sys::AParcel_readBool; @@ -537,8 +540,6 @@ impl SerializeOption for str { } } -impl SerializeArray for Option<&str> {} - impl Serialize for str { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Some(self).serialize(parcel) @@ -561,8 +562,6 @@ impl SerializeOption for String { } } -impl SerializeArray for Option<String> {} - impl Deserialize for Option<String> { fn deserialize(parcel: &Parcel) -> Result<Self> { let mut vec: Option<Vec<u8>> = None; diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs index a7a3fb276e..a8d0c33034 100644 --- a/libs/binder/rust/src/proxy.rs +++ b/libs/binder/rust/src/proxy.rs @@ -427,7 +427,6 @@ impl SerializeOption for SpIBinder { } impl SerializeArray for SpIBinder {} -impl SerializeArray for Option<&SpIBinder> {} impl Deserialize for SpIBinder { fn deserialize(parcel: &Parcel) -> Result<SpIBinder> { @@ -445,7 +444,6 @@ impl DeserializeOption for SpIBinder { } impl DeserializeArray for SpIBinder {} -impl DeserializeArray for Option<SpIBinder> {} /// A weak reference to a Binder remote object. /// diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp index 23e34aa8ef..777f3c9354 100644 --- a/libs/binder/servicedispatcher.cpp +++ b/libs/binder/servicedispatcher.cpp @@ -90,7 +90,6 @@ int Dispatch(const char* name, const ServiceRetriever& serviceRetriever) { LOG(ERROR) << "Cannot create RpcServer"; return EX_SOFTWARE; } - rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); unsigned int port; if (status_t status = rpcServer->setupInetServer(kLocalInetAddress, 0, &port); status != OK) { LOG(ERROR) << "setupInetServer failed: " << statusToString(status); @@ -207,7 +206,6 @@ int wrapServiceManager(const ServiceRetriever& serviceRetriever) { service = ServiceManagerProxyToNative::asBinder(interface); auto rpcServer = RpcServer::make(); - rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); rpcServer->setRootObject(service); unsigned int port; if (status_t status = rpcServer->setupInetServer(kLocalInetAddress, 0, &port); status != OK) { diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl index 9e1078870c..fdd02a4435 100644 --- a/libs/binder/tests/IBinderRpcTest.aidl +++ b/libs/binder/tests/IBinderRpcTest.aidl @@ -18,6 +18,9 @@ interface IBinderRpcTest { oneway void sendString(@utf8InCpp String str); @utf8InCpp String doubleString(@utf8InCpp String str); + // get the port that a client used to connect to this object + int getClientPort(); + // number of known RPC binders to process, RpcState::countBinders by session int[] countBinders(); diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index 639876ffe3..4d316f72f0 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -436,6 +436,11 @@ class TestDeathRecipient : public IBinder::DeathRecipient, public BinderLibTestE }; }; +TEST_F(BinderLibTest, CannotUseBinderAfterFork) { + // EXPECT_DEATH works by forking the process + EXPECT_DEATH({ ProcessState::self(); }, "libbinder ProcessState can not be used after fork"); +} + TEST_F(BinderLibTest, WasParceled) { auto binder = sp<BBinder>::make(); EXPECT_FALSE(binder->wasParceled()); @@ -1197,7 +1202,6 @@ public: auto rpcServer = RpcServer::make(); EXPECT_NE(nullptr, rpcServer); if (rpcServer == nullptr) return {}; - rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); unsigned int port; if (status_t status = rpcServer->setupInetServer("127.0.0.1", 0, &port); status != OK) { ADD_FAILURE() << "setupInetServer failed" << statusToString(status); diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp index f8718aad1e..52ba9b00fd 100644 --- a/libs/binder/tests/binderRpcBenchmark.cpp +++ b/libs/binder/tests/binderRpcBenchmark.cpp @@ -206,7 +206,6 @@ void forkRpcServer(const char* addr, const sp<RpcServer>& server) { if (0 == fork()) { prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay server->setRootObject(sp<MyBinderRpcBenchmark>::make()); - server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); CHECK_EQ(OK, server->setupUnixDomainServer(addr)); server->join(); exit(1); diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index d68c6fffd1..0cbb88038b 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -109,7 +109,6 @@ TEST_P(BinderRpcSimple, SetExternalServerTest) { base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR))); int sinkFd = sink.get(); auto server = RpcServer::make(newFactory(GetParam())); - server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); ASSERT_FALSE(server->hasServer()); ASSERT_EQ(OK, server->setupExternalServer(std::move(sink))); ASSERT_TRUE(server->hasServer()); @@ -174,6 +173,7 @@ public: class MyBinderRpcTest : public BnBinderRpcTest { public: wp<RpcServer> server; + int port = 0; Status sendString(const std::string& str) override { (void)str; @@ -183,6 +183,10 @@ public: *strstr = str + str; return Status::ok(); } + Status getClientPort(int* out) override { + *out = port; + return Status::ok(); + } Status countBinders(std::vector<int32_t>* out) override { sp<RpcServer> spServer = server.promote(); if (spServer == nullptr) { @@ -538,7 +542,6 @@ public: auto certVerifier = std::make_shared<RpcCertificateVerifierSimple>(); sp<RpcServer> server = RpcServer::make(newFactory(rpcSecurity, certVerifier)); - server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); server->setMaxThreads(options.numThreads); unsigned int outPort = 0; @@ -643,13 +646,39 @@ public: BinderRpcTestProcessSession createRpcTestSocketServerProcess(const Options& options) { BinderRpcTestProcessSession ret{ - .proc = createRpcTestSocketServerProcess(options, - [&](const sp<RpcServer>& server) { - sp<MyBinderRpcTest> service = - new MyBinderRpcTest; - server->setRootObject(service); - service->server = server; - }), + .proc = createRpcTestSocketServerProcess( + options, + [&](const sp<RpcServer>& server) { + server->setPerSessionRootObject([&](const sockaddr* addr, + socklen_t len) { + sp<MyBinderRpcTest> service = sp<MyBinderRpcTest>::make(); + switch (addr->sa_family) { + case AF_UNIX: + // nothing to save + break; + case AF_VSOCK: + CHECK_EQ(len, sizeof(sockaddr_vm)); + service->port = reinterpret_cast<const sockaddr_vm*>(addr) + ->svm_port; + break; + case AF_INET: + CHECK_EQ(len, sizeof(sockaddr_in)); + service->port = reinterpret_cast<const sockaddr_in*>(addr) + ->sin_port; + break; + case AF_INET6: + CHECK_EQ(len, sizeof(sockaddr_in)); + service->port = reinterpret_cast<const sockaddr_in6*>(addr) + ->sin6_port; + break; + default: + LOG_ALWAYS_FATAL("Unrecognized address family %d", + addr->sa_family); + } + service->server = server; + return service; + }); + }), }; ret.rootBinder = ret.proc.sessions.at(0).root; @@ -682,6 +711,27 @@ TEST_P(BinderRpc, MultipleSessions) { } } +TEST_P(BinderRpc, SeparateRootObject) { + SocketType type = std::get<0>(GetParam()); + if (type == SocketType::PRECONNECTED || type == SocketType::UNIX) { + // we can't get port numbers for unix sockets + return; + } + + auto proc = createRpcTestSocketServerProcess({.numSessions = 2}); + + int port1 = 0; + EXPECT_OK(proc.rootIface->getClientPort(&port1)); + + sp<IBinderRpcTest> rootIface2 = interface_cast<IBinderRpcTest>(proc.proc.sessions.at(1).root); + int port2; + EXPECT_OK(rootIface2->getClientPort(&port2)); + + // we should have a different IBinderRpcTest object created for each + // session, because we use setPerSessionRootObject + EXPECT_NE(port1, port2); +} + TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) { auto proc = createRpcTestSocketServerProcess({}); Parcel data; @@ -690,13 +740,21 @@ TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) { } TEST_P(BinderRpc, AppendSeparateFormats) { - auto proc = createRpcTestSocketServerProcess({}); + auto proc1 = createRpcTestSocketServerProcess({}); + auto proc2 = createRpcTestSocketServerProcess({}); + + Parcel pRaw; Parcel p1; - p1.markForBinder(proc.rootBinder); + p1.markForBinder(proc1.rootBinder); p1.writeInt32(3); + EXPECT_EQ(BAD_TYPE, p1.appendFrom(&pRaw, 0, p1.dataSize())); + EXPECT_EQ(BAD_TYPE, pRaw.appendFrom(&p1, 0, p1.dataSize())); + Parcel p2; + p2.markForBinder(proc2.rootBinder); + p2.writeInt32(7); EXPECT_EQ(BAD_TYPE, p1.appendFrom(&p2, 0, p2.dataSize())); EXPECT_EQ(BAD_TYPE, p2.appendFrom(&p1, 0, p1.dataSize())); @@ -1299,11 +1357,20 @@ TEST_P(BinderRpc, Fds) { ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?"); } +TEST_P(BinderRpc, AidlDelegatorTest) { + auto proc = createRpcTestSocketServerProcess({}); + auto myDelegator = sp<IBinderRpcTestDelegator>::make(proc.rootIface); + ASSERT_NE(nullptr, myDelegator); + + std::string doubled; + EXPECT_OK(myDelegator->doubleString("cool ", &doubled)); + EXPECT_EQ("cool cool ", doubled); +} + static bool testSupportVsockLoopback() { // We don't need to enable TLS to know if vsock is supported. unsigned int vsockPort = allocateVsockPort(); sp<RpcServer> server = RpcServer::make(RpcTransportCtxFactoryRaw::make()); - server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); if (status_t status = server->setupVsockServer(vsockPort); status != OK) { if (status == -EAFNOSUPPORT) { return false; @@ -1392,7 +1459,6 @@ private: TEST_P(BinderRpcSimple, Shutdown) { auto addr = allocateSocketAddress(); auto server = RpcServer::make(newFactory(GetParam())); - server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); ASSERT_EQ(OK, server->setupUnixDomainServer(addr.c_str())); auto joinEnds = std::make_shared<OneOffSignal>(); @@ -1432,7 +1498,6 @@ TEST(BinderRpc, Java) { ASSERT_EQ(OK, binder->pingBinder()); auto rpcServer = RpcServer::make(); - rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); unsigned int port; ASSERT_EQ(OK, rpcServer->setupInetServer(kLocalInetAddress, 0, &port)); auto socket = rpcServer->releaseServer(); @@ -1471,7 +1536,6 @@ public: std::unique_ptr<RpcAuth> auth = std::make_unique<RpcAuthSelfSigned>()) { auto [socketType, rpcSecurity, certificateFormat] = param; auto rpcServer = RpcServer::make(newFactory(rpcSecurity)); - rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); switch (socketType) { case SocketType::PRECONNECTED: { return AssertionFailure() << "Not supported by this test"; diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp index 55eb847436..e4f57b0121 100644 --- a/libs/binder/tests/parcel_fuzzer/binder.cpp +++ b/libs/binder/tests/parcel_fuzzer/binder.cpp @@ -284,7 +284,6 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { FUZZ_LOG() << "readObject: " << obj; }, PARCEL_READ_NO_STATUS(uid_t, readCallingWorkSourceUid), - PARCEL_READ_NO_STATUS(size_t, getBlobAshmemSize), PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize), // additional parcelable objects defined in libbinder @@ -306,7 +305,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { size_t offset = p.readUint32(); size_t length = p.readUint32(); bool result; - status_t status = p.hasFileDescriptorsInRange(offset, length, result); + status_t status = p.hasFileDescriptorsInRange(offset, length, &result); FUZZ_LOG() << " status: " << status << " result: " << result; }, }; diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp index 6b783a4804..c0a762d1de 100644 --- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp +++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp @@ -95,6 +95,11 @@ std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<SomeParcelable>, ndk::AParcel_readVector), + PARCEL_READ(std::optional<std::vector<std::optional<SomeParcelable>>>, ndk::AParcel_readVector), + PARCEL_READ(std::vector<ndk::SpAIBinder>, ndk::AParcel_readVector), + PARCEL_READ(std::optional<std::vector<ndk::SpAIBinder>>, ndk::AParcel_readVector), + PARCEL_READ(std::vector<ndk::ScopedFileDescriptor>, ndk::AParcel_readVector), + PARCEL_READ(std::optional<std::vector<ndk::ScopedFileDescriptor>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector), diff --git a/libs/binder/tests/rpc_fuzzer/Android.bp b/libs/binder/tests/rpc_fuzzer/Android.bp index c0f0a12121..71e847fd1e 100644 --- a/libs/binder/tests/rpc_fuzzer/Android.bp +++ b/libs/binder/tests/rpc_fuzzer/Android.bp @@ -14,6 +14,7 @@ cc_fuzz { fuzz_config: { cc: ["smoreland@google.com"], }, + corpus: ["corpus/*"], dictionary: "binder_rpc_fuzzer.dict", srcs: [ diff --git a/libs/binder/tests/rpc_fuzzer/corpus/special_transaction b/libs/binder/tests/rpc_fuzzer/corpus/special_transaction Binary files differnew file mode 100644 index 0000000000..37228ee8cd --- /dev/null +++ b/libs/binder/tests/rpc_fuzzer/corpus/special_transaction diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp index 518849a3e4..a8713a24d6 100644 --- a/libs/binder/tests/rpc_fuzzer/main.cpp +++ b/libs/binder/tests/rpc_fuzzer/main.cpp @@ -119,7 +119,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { sp<RpcServer> server = RpcServer::make(makeTransportCtxFactory(&provider)); server->setRootObject(sp<SomeBinder>::make()); - server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); CHECK_EQ(OK, server->setupUnixDomainServer(kSock.c_str())); std::thread serverThread([=] { (void)server->join(); }); @@ -158,6 +157,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { } } + usleep(10000); + if (hangupBeforeShutdown) { connections.clear(); while (!server->listSessions().empty() || server->numUninitializedSessions()) { diff --git a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp index 20c55699cc..e77c55c669 100644 --- a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp +++ b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp @@ -44,7 +44,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { auto thread = std::thread([&]() { prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay server->setRootObject(sp<BBinder>::make()); - server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); CHECK_EQ(OK, server->setupUnixDomainServer(addr.c_str())); server->join(); }); diff --git a/libs/permission/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h index e3d705fa35..abcd527966 100644 --- a/libs/permission/include/binder/AppOpsManager.h +++ b/libs/permission/include/binder/AppOpsManager.h @@ -147,7 +147,8 @@ public: OP_ACTIVITY_RECOGNITION_SOURCE = 113, OP_BLUETOOTH_ADVERTISE = 114, OP_RECORD_INCOMING_PHONE_AUDIO = 115, - _NUM_OP = 116 + OP_NEARBY_WIFI_DEVICES = 116, + _NUM_OP = 117 }; AppOpsManager(); diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index ae8f2384c4..cc627b8bc8 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -388,7 +388,10 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { drawBlurLayers(renderengine, display, dstTexture); } - // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; + // The majority of skia shaders needed by RenderEngine are related to sampling images. + // These need to be generated with various source textures. + // Make a list of applicable sources. + // GRALLOC_USAGE_HW_TEXTURE should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE. const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE; sp<GraphicBuffer> externalBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, @@ -396,24 +399,24 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { const auto externalTexture = std::make_shared<ExternalTexture>(externalBuffer, *renderengine, ExternalTexture::Usage::READABLE); + std::vector<const std::shared_ptr<ExternalTexture>> textures = + {srcTexture, externalTexture}; - // Another external texture with a different pixel format triggers useIsOpaqueWorkaround + // Another external texture with a different pixel format triggers useIsOpaqueWorkaround. + // It doesn't have to be f16, but it can't be the usual 8888. sp<GraphicBuffer> f16ExternalBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_FP16, 1, usageExternal, "primeShaderCache_external_f16"); - const auto f16ExternalTexture = + // The F16 texture may not be usable on all devices, so check first that it was created. + status_t error = f16ExternalBuffer->initCheck(); + if (!error) { + const auto f16ExternalTexture = std::make_shared<ExternalTexture>(f16ExternalBuffer, *renderengine, ExternalTexture::Usage::READABLE); + textures.push_back(f16ExternalTexture); + } - // The majority of shaders are related to sampling images. - // These need to be generated with various source textures - // The F16 texture may not be usable on all devices, so check first that it was created with - // the requested usage bit. - auto textures = {srcTexture, externalTexture}; - auto texturesWithF16 = {srcTexture, externalTexture, f16ExternalTexture}; - bool canUsef16 = f16ExternalBuffer->getUsage() & GRALLOC_USAGE_HW_TEXTURE; - - for (auto texture : canUsef16 ? texturesWithF16 : textures) { + for (auto texture : textures) { drawImageLayers(renderengine, display, dstTexture, texture); // Draw layers for b/185569240. drawClippedLayers(renderengine, display, dstTexture, texture); |