diff options
36 files changed, 691 insertions, 124 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 0e9ce897bc..24b201f8ab 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -2418,7 +2418,7 @@ void Dumpstate::DumpstateBoard(int out_fd) { // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we // will kill the HAL and grab whatever it dumped in time. - constexpr size_t timeout_sec = 30; + constexpr size_t timeout_sec = 45; if (dumpstate_hal_handle_aidl != nullptr) { DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode, diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 7448308ec9..63d87dae5a 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -166,6 +166,7 @@ cc_library { "-Wextra-semi", "-Werror", "-Wzero-as-null-pointer-constant", + "-Wreorder-init-list", "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION", "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION", ], diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index 0970ca5aa5..01b25d390d 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -19,6 +19,7 @@ #include <atomic> #include <set> +#include <android-base/logging.h> #include <android-base/unique_fd.h> #include <binder/BpBinder.h> #include <binder/IInterface.h> @@ -281,9 +282,11 @@ status_t BBinder::transact( err = pingBinder(); break; case EXTENSION_TRANSACTION: + CHECK(reply != nullptr); err = reply->writeStrongBinder(getExtension()); break; case DEBUG_PID_TRANSACTION: + CHECK(reply != nullptr); err = reply->writeInt32(getDebugPid()); break; case SET_RPC_CLIENT_TRANSACTION: { @@ -590,6 +593,7 @@ status_t BBinder::onTransact( { switch (code) { case INTERFACE_TRANSACTION: + CHECK(reply != nullptr); reply->writeString16(getInterfaceDescriptor()); return NO_ERROR; diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 056ef0ab74..921e57c7bf 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -72,29 +72,29 @@ void* BpBinder::ObjectManager::attach(const void* objectID, void* object, void* e.cleanupCookie = cleanupCookie; e.func = func; - if (ssize_t idx = mObjects.indexOfKey(objectID); idx >= 0) { + if (mObjects.find(objectID) != mObjects.end()) { ALOGI("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object " "ID already in use", objectID, this, object); - return mObjects[idx].object; + return mObjects[objectID].object; } - mObjects.add(objectID, e); + mObjects.insert({objectID, e}); return nullptr; } void* BpBinder::ObjectManager::find(const void* objectID) const { - const ssize_t i = mObjects.indexOfKey(objectID); - if (i < 0) return nullptr; - return mObjects.valueAt(i).object; + auto i = mObjects.find(objectID); + if (i == mObjects.end()) return nullptr; + return i->second.object; } void* BpBinder::ObjectManager::detach(const void* objectID) { - ssize_t idx = mObjects.indexOfKey(objectID); - if (idx < 0) return nullptr; - void* value = mObjects[idx].object; - mObjects.removeItemsAt(idx, 1); + auto i = mObjects.find(objectID); + if (i == mObjects.end()) return nullptr; + void* value = i->second.object; + mObjects.erase(i); return value; } @@ -102,10 +102,10 @@ void BpBinder::ObjectManager::kill() { const size_t N = mObjects.size(); ALOGV("Killing %zu objects in manager %p", N, this); - for (size_t i=0; i<N; i++) { - const entry_t& e = mObjects.valueAt(i); + for (auto i : mObjects) { + const entry_t& e = i.second; if (e.func != nullptr) { - e.func(mObjects.keyAt(i), e.object, e.cleanupCookie); + e.func(i.first, e.object, e.cleanupCookie); } } diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp index bd974b02b1..9c7ff97a48 100644 --- a/libs/binder/IMemory.cpp +++ b/libs/binder/IMemory.cpp @@ -31,9 +31,10 @@ #include <binder/Parcel.h> #include <log/log.h> -#include <utils/KeyedVector.h> #include <utils/threads.h> +#include <map> + #define VERBOSE 0 namespace android { @@ -63,7 +64,7 @@ private: void free_heap(const wp<IBinder>& binder); Mutex mHeapCacheLock; // Protects entire vector below. - KeyedVector< wp<IBinder>, heap_info_t > mHeapCache; + std::map<wp<IBinder>, heap_info_t> mHeapCache; // We do not use the copy-on-write capabilities of KeyedVector. // TODO: Reimplemement based on standard C++ container? }; @@ -434,9 +435,9 @@ void HeapCache::binderDied(const wp<IBinder>& binder) sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder) { Mutex::Autolock _l(mHeapCacheLock); - ssize_t i = mHeapCache.indexOfKey(binder); - if (i>=0) { - heap_info_t& info = mHeapCache.editValueAt(i); + auto i = mHeapCache.find(binder); + if (i != mHeapCache.end()) { + heap_info_t& info = i->second; ALOGD_IF(VERBOSE, "found binder=%p, heap=%p, size=%zu, fd=%d, count=%d", binder.get(), info.heap.get(), @@ -452,7 +453,7 @@ sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder) info.count = 1; //ALOGD("adding binder=%p, heap=%p, count=%d", // binder.get(), info.heap.get(), info.count); - mHeapCache.add(binder, info); + mHeapCache.insert({binder, info}); return info.heap; } } @@ -466,9 +467,9 @@ void HeapCache::free_heap(const wp<IBinder>& binder) sp<IMemoryHeap> rel; { Mutex::Autolock _l(mHeapCacheLock); - ssize_t i = mHeapCache.indexOfKey(binder); - if (i>=0) { - heap_info_t& info(mHeapCache.editValueAt(i)); + auto i = mHeapCache.find(binder); + if (i != mHeapCache.end()) { + heap_info_t& info = i->second; if (--info.count == 0) { ALOGD_IF(VERBOSE, "removing binder=%p, heap=%p, size=%zu, fd=%d, count=%d", @@ -477,8 +478,8 @@ void HeapCache::free_heap(const wp<IBinder>& binder) static_cast<BpMemoryHeap*>(info.heap.get()) ->mHeapId.load(memory_order_relaxed), info.count); - rel = mHeapCache.valueAt(i).heap; - mHeapCache.removeItemsAt(i); + rel = i->second.heap; + mHeapCache.erase(i); } } else { ALOGE("free_heap binder=%p not found!!!", binder.unsafe_get()); @@ -490,23 +491,23 @@ sp<IMemoryHeap> HeapCache::get_heap(const sp<IBinder>& binder) { sp<IMemoryHeap> realHeap; Mutex::Autolock _l(mHeapCacheLock); - ssize_t i = mHeapCache.indexOfKey(binder); - if (i>=0) realHeap = mHeapCache.valueAt(i).heap; - else realHeap = interface_cast<IMemoryHeap>(binder); + auto i = mHeapCache.find(binder); + if (i != mHeapCache.end()) + realHeap = i->second.heap; + else + realHeap = interface_cast<IMemoryHeap>(binder); return realHeap; } void HeapCache::dump_heaps() { Mutex::Autolock _l(mHeapCacheLock); - int c = mHeapCache.size(); - for (int i=0 ; i<c ; i++) { - const heap_info_t& info = mHeapCache.valueAt(i); + for (const auto& i : mHeapCache) { + const heap_info_t& info = i.second; BpMemoryHeap const* h(static_cast<BpMemoryHeap const *>(info.heap.get())); - ALOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%zu)", - mHeapCache.keyAt(i).unsafe_get(), - info.heap.get(), info.count, - h->mHeapId.load(memory_order_relaxed), h->mBase, h->mSize); + ALOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%zu)", i.first.unsafe_get(), + info.heap.get(), info.count, h->mHeapId.load(memory_order_relaxed), h->mBase, + h->mSize); } } diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 13f0a4c4a5..f79075d260 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -1199,7 +1199,8 @@ status_t IPCThreadState::executeCommand(int32_t cmd) case BR_DECREFS: refs = (RefBase::weakref_type*)mIn.readPointer(); - obj = (BBinder*)mIn.readPointer(); + // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores) + obj = (BBinder*)mIn.readPointer(); // consume // NOTE: This assertion is not valid, because the object may no // longer exist (thus the (BBinder*)cast above resulting in a different // memory address). @@ -1409,7 +1410,7 @@ status_t IPCThreadState::getProcessFreezeInfo(pid_t pid, uint32_t *sync_received uint32_t *async_received) { int ret = 0; - binder_frozen_status_info info; + binder_frozen_status_info info = {}; info.pid = pid; #if defined(__ANDROID__) diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp index e1cbc1996d..8132d46940 100644 --- a/libs/binder/MemoryHeapBase.cpp +++ b/libs/binder/MemoryHeapBase.cpp @@ -18,10 +18,13 @@ #include <errno.h> #include <fcntl.h> +#include <linux/memfd.h> #include <stdint.h> #include <stdlib.h> #include <sys/ioctl.h> +#include <sys/mman.h> #include <sys/stat.h> +#include <sys/syscall.h> #include <sys/types.h> #include <unistd.h> @@ -34,6 +37,24 @@ namespace android { // --------------------------------------------------------------------------- +#ifdef __BIONIC__ +static int memfd_create_region(const char* name, size_t size) { + int fd = memfd_create(name, MFD_CLOEXEC | MFD_ALLOW_SEALING); + if (fd == -1) { + ALOGE("%s: memfd_create(%s, %zd) failed: %s\n", __func__, name, size, strerror(errno)); + return -1; + } + + if (ftruncate(fd, size) == -1) { + ALOGE("%s, ftruncate(%s, %zd) failed for memfd creation: %s\n", __func__, name, size, + strerror(errno)); + close(fd); + return -1; + } + return fd; +} +#endif + MemoryHeapBase::MemoryHeapBase() : mFD(-1), mSize(0), mBase(MAP_FAILED), mDevice(nullptr), mNeedUnmap(false), mOffset(0) @@ -45,15 +66,36 @@ MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) mDevice(nullptr), mNeedUnmap(false), mOffset(0) { const size_t pagesize = getpagesize(); - size = ((size + pagesize-1) & ~(pagesize-1)); - int fd = ashmem_create_region(name == nullptr ? "MemoryHeapBase" : name, size); - ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno)); - if (fd >= 0) { - if (mapfd(fd, true, size) == NO_ERROR) { - if (flags & READ_ONLY) { - ashmem_set_prot_region(fd, PROT_READ); - } + size = ((size + pagesize - 1) & ~(pagesize - 1)); + int fd = -1; + if (mFlags & FORCE_MEMFD) { +#ifdef __BIONIC__ + ALOGV("MemoryHeapBase: Attempting to force MemFD"); + fd = memfd_create_region(name ? name : "MemoryHeapBase", size); + if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return; + const int SEAL_FLAGS = ((mFlags & READ_ONLY) ? F_SEAL_FUTURE_WRITE : 0) | + ((mFlags & MEMFD_ALLOW_SEALING) ? 0 : F_SEAL_SEAL); + if (SEAL_FLAGS && (fcntl(fd, F_ADD_SEALS, SEAL_FLAGS) == -1)) { + ALOGE("MemoryHeapBase: MemFD %s sealing with flags %x failed with error %s", name, + SEAL_FLAGS, strerror(errno)); + munmap(mBase, mSize); + mBase = nullptr; + mSize = 0; + close(fd); } + return; +#else + mFlags &= ~(FORCE_MEMFD | MEMFD_ALLOW_SEALING); +#endif + } + if (mFlags & MEMFD_ALLOW_SEALING) { + LOG_ALWAYS_FATAL("Invalid Flags. MEMFD_ALLOW_SEALING only valid with FORCE_MEMFD."); + } + fd = ashmem_create_region(name ? name : "MemoryHeapBase", size); + ALOGE_IF(fd < 0, "MemoryHeapBase: error creating ashmem region: %s", strerror(errno)); + if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return; + if (mFlags & READ_ONLY) { + ashmem_set_prot_region(fd, PROT_READ); } } @@ -61,6 +103,9 @@ MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), mDevice(nullptr), mNeedUnmap(false), mOffset(0) { + if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) { + LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor"); + } int open_flags = O_RDWR; if (flags & NO_CACHING) open_flags |= O_SYNC; @@ -80,6 +125,9 @@ MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, off_t offset : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), mDevice(nullptr), mNeedUnmap(false), mOffset(0) { + if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) { + LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor"); + } const size_t pagesize = getpagesize(); size = ((size + pagesize-1) & ~(pagesize-1)); mapfd(fcntl(fd, F_DUPFD_CLOEXEC, 0), false, size, offset); diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 6a138e340f..504c6c2d83 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -63,7 +63,7 @@ // This macro should never be used at runtime, as a too large value // of s could cause an integer overflow. Instead, you should always // use the wrapper function pad_size() -#define PAD_SIZE_UNSAFE(s) (((s)+3)&~3) +#define PAD_SIZE_UNSAFE(s) (((s) + 3) & ~3UL) static size_t pad_size(size_t s) { if (s > (std::numeric_limits<size_t>::max() - 3)) { diff --git a/libs/binder/ParcelableHolder.cpp b/libs/binder/ParcelableHolder.cpp index 2e86b7415a..3cf94e3047 100644 --- a/libs/binder/ParcelableHolder.cpp +++ b/libs/binder/ParcelableHolder.cpp @@ -52,7 +52,10 @@ status_t ParcelableHolder::writeToParcel(Parcel* p) const { } status_t ParcelableHolder::readFromParcel(const Parcel* p) { - this->mStability = static_cast<Stability>(p->readInt32()); + int32_t wireStability; + if (status_t status = p->readInt32(&wireStability); status != OK) return status; + if (static_cast<int32_t>(this->mStability) != wireStability) return BAD_VALUE; + this->mParcelable = nullptr; this->mParcelableName = std::nullopt; int32_t rawDataSize; diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index baa817c6b9..b14a838447 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -409,6 +409,28 @@ size_t ProcessState::getThreadPoolMaxThreadCount() const { return 0; } +#define DRIVER_FEATURES_PATH "/dev/binderfs/features/" +bool ProcessState::isDriverFeatureEnabled(const DriverFeature feature) { + static const char* const names[] = { + [static_cast<int>(DriverFeature::ONEWAY_SPAM_DETECTION)] = + DRIVER_FEATURES_PATH "oneway_spam_detection", + }; + int fd = open(names[static_cast<int>(feature)], O_RDONLY | O_CLOEXEC); + char on; + if (fd == -1) { + ALOGE_IF(errno != ENOENT, "%s: cannot open %s: %s", __func__, + names[static_cast<int>(feature)], strerror(errno)); + return false; + } + if (read(fd, &on, sizeof(on)) == -1) { + ALOGE("%s: error reading to %s: %s", __func__, + names[static_cast<int>(feature)], strerror(errno)); + return false; + } + close(fd); + return on == '1'; +} + status_t ProcessState::enableOnewaySpamDetection(bool enable) { uint32_t enableDetection = enable ? 1 : 0; if (ioctl(mDriverFD, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enableDetection) == -1) { @@ -452,7 +474,9 @@ static base::Result<int> open_driver(const char* driver) { 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)); + ALOGE_IF(ProcessState::isDriverFeatureEnabled( + ProcessState::DriverFeature::ONEWAY_SPAM_DETECTION), + "Binder ioctl to enable oneway spam detection failed: %s", strerror(errno)); } return fd; } diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp index b84395e7cb..d40778a3d8 100644 --- a/libs/binder/RpcSession.cpp +++ b/libs/binder/RpcSession.cpp @@ -152,8 +152,13 @@ status_t RpcSession::setupInetClient(const char* addr, unsigned int port) { } status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) { - return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) -> status_t { - // std::move'd from fd becomes -1 (!ok()) + // Why passing raw fd? When fd is passed as reference, Clang analyzer sees that the variable + // `fd` is a moved-from object. To work-around the issue, unwrap the raw fd from the outer `fd`, + // pass the raw fd by value to the lambda, and then finally wrap it in unique_fd inside the + // lambda. + return setupClient([&, raw = fd.release()](const std::vector<uint8_t>& sessionId, + bool incoming) -> status_t { + unique_fd fd(raw); if (!fd.ok()) { fd = request(); if (!fd.ok()) return BAD_VALUE; @@ -848,10 +853,16 @@ status_t RpcSession::ExclusiveConnection::find(const sp<RpcSession>& session, Co } if (session->mConnections.mOutgoing.size() == 0) { - ALOGE("Session has no client connections. This is required for an RPC server to make " - "any non-nested (e.g. oneway or on another thread) calls. Use: %d. Server " - "connections: %zu", - static_cast<int>(use), session->mConnections.mIncoming.size()); + ALOGE("Session has no outgoing connections. This is required for an RPC server to make " + "any non-nested (e.g. oneway or on another thread) calls. Use code request " + "reason: %d. Incoming connections: %zu. %s.", + static_cast<int>(use), session->mConnections.mIncoming.size(), + (session->server() + ? "This is a server session, so see RpcSession::setMaxIncomingThreads " + "for the corresponding client" + : "This is a client session, so see RpcSession::setMaxOutgoingThreads " + "for this client or RpcServer::setMaxThreads for the corresponding " + "server")); return WOULD_BLOCK; } diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp index 4ddbce71a8..2e7084e12e 100644 --- a/libs/binder/RpcState.cpp +++ b/libs/binder/RpcState.cpp @@ -125,8 +125,8 @@ status_t RpcState::onBinderLeaving(const sp<RpcSession>& session, const sp<IBind auto&& [it, inserted] = mNodeForAddress.insert({RpcWireAddress::toRaw(address), BinderNode{ .binder = binder, - .timesSent = 1, .sentRef = binder, + .timesSent = 1, }}); if (inserted) { *outAddress = it->first; diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h index c0454b6fbd..8deb2fe4a8 100644 --- a/libs/binder/include/binder/BpBinder.h +++ b/libs/binder/include/binder/BpBinder.h @@ -17,10 +17,10 @@ #pragma once #include <binder/IBinder.h> -#include <utils/KeyedVector.h> #include <utils/Mutex.h> #include <utils/threads.h> +#include <map> #include <unordered_map> #include <variant> @@ -110,7 +110,7 @@ public: IBinder::object_cleanup_func func; }; - KeyedVector<const void*, entry_t> mObjects; + std::map<const void*, entry_t> mObjects; }; class PrivateAccessor { diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index ea40db8ffa..bb55831ec2 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -56,8 +56,16 @@ public: static const int DUMP_FLAG_PROTO = 1 << 4; /** - * Retrieve an existing service, blocking for a few seconds - * if it doesn't yet exist. + * Retrieve an existing service, blocking for a few seconds if it doesn't yet exist. This + * does polling. A more efficient way to make sure you unblock as soon as the service is + * available is to use waitForService or to use service notifications. + * + * Warning: when using this API, typically, you should call it in a loop. It's dangerous to + * assume that nullptr could mean that the service is not available. The service could just + * be starting. Generally, whether a service exists, this information should be declared + * externally (for instance, an Android feature might imply the existence of a service, + * a system property, or in the case of services in the VINTF manifest, it can be checked + * with isDeclared). */ virtual sp<IBinder> getService( const String16& name) const = 0; diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h index dd76943ac7..15dd28f08e 100644 --- a/libs/binder/include/binder/MemoryHeapBase.h +++ b/libs/binder/include/binder/MemoryHeapBase.h @@ -34,7 +34,21 @@ public: // memory won't be mapped locally, but will be mapped in the remote // process. DONT_MAP_LOCALLY = 0x00000100, - NO_CACHING = 0x00000200 + NO_CACHING = 0x00000200, + // Bypass ashmem-libcutils to create a memfd shared region. + // Ashmem-libcutils will eventually migrate to memfd. + // Memfd has security benefits and supports file sealing. + // Calling process will need to modify selinux permissions to + // open access to tmpfs files. See audioserver for examples. + // This is only valid for size constructor. + // For host compilation targets, memfd is stubbed in favor of /tmp + // files so sealing is not enforced. + FORCE_MEMFD = 0x00000400, + // Default opt-out of sealing behavior in memfd to avoid potential DOS. + // Clients of shared files can seal at anytime via syscall, leading to + // TOC/TOU issues if additional seals prevent access from the creating + // process. Alternatively, seccomp fcntl(). + MEMFD_ALLOW_SEALING = 0x00000800 }; /* diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h index cf8d8e433c..0deee73e43 100644 --- a/libs/binder/include/binder/ProcessState.h +++ b/libs/binder/include/binder/ProcessState.h @@ -91,6 +91,12 @@ public: */ size_t getThreadPoolMaxThreadCount() const; + enum class DriverFeature { + ONEWAY_SPAM_DETECTION, + }; + // Determine whether a feature is supported by the binder driver. + static bool isDriverFeatureEnabled(const DriverFeature feature); + private: static sp<ProcessState> init(const char* defaultDriver, bool requireDefault); 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 2c471c6e8f..7ea9be797b 100644 --- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h +++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h @@ -268,7 +268,11 @@ class ScopedAStatus : public impl::ScopedAResource<AStatus*, AStatus_delete, nul const char* getMessage() const { return AStatus_getMessage(get()); } std::string getDescription() const { +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 30, *)) { +#else + if (__ANDROID_API__ >= 30) { +#endif const char* cStr = AStatus_getDescription(get()); std::string ret = cStr; AStatus_deleteDescription(cStr); diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h index 09411e76a3..b3bc7f449e 100644 --- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h +++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h @@ -256,7 +256,11 @@ AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor, // ourselves. The defaults are harmless. AIBinder_Class_setOnDump(clazz, ICInterfaceData::onDump); #ifdef HAS_BINDER_SHELL_COMMAND +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 30, *)) { +#else + if (__ANDROID_API__ >= 30) { +#endif AIBinder_Class_setHandleShellCommand(clazz, ICInterfaceData::handleShellCommand); } #endif diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h index 972eca79ff..f45aa7631b 100644 --- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h +++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h @@ -51,7 +51,11 @@ class AParcelableHolder { AParcelableHolder(const AParcelableHolder& other) : mParcel(AParcel_create()), mStability(other.mStability) { // AParcelableHolder has been introduced in 31. +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 31, *)) { +#else + if (__ANDROID_API__ >= 31) { +#endif AParcel_appendFrom(other.mParcel.get(), this->mParcel.get(), 0, AParcel_getDataSize(other.mParcel.get())); } @@ -63,13 +67,21 @@ class AParcelableHolder { binder_status_t writeToParcel(AParcel* parcel) const { RETURN_ON_FAILURE(AParcel_writeInt32(parcel, static_cast<int32_t>(this->mStability))); +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 31, *)) { +#else + if (__ANDROID_API__ >= 31) { +#endif int32_t size = AParcel_getDataSize(this->mParcel.get()); RETURN_ON_FAILURE(AParcel_writeInt32(parcel, size)); } else { return STATUS_INVALID_OPERATION; } +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 31, *)) { +#else + if (__ANDROID_API__ >= 31) { +#endif int32_t size = AParcel_getDataSize(this->mParcel.get()); RETURN_ON_FAILURE(AParcel_appendFrom(this->mParcel.get(), parcel, 0, size)); } else { @@ -79,13 +91,22 @@ class AParcelableHolder { } binder_status_t readFromParcel(const AParcel* parcel) { +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 31, *)) { +#else + if (__ANDROID_API__ >= 31) { +#endif AParcel_reset(mParcel.get()); } else { return STATUS_INVALID_OPERATION; } - RETURN_ON_FAILURE(AParcel_readInt32(parcel, &this->mStability)); + parcelable_stability_t wireStability; + RETURN_ON_FAILURE(AParcel_readInt32(parcel, &wireStability)); + if (this->mStability != wireStability) { + return STATUS_BAD_VALUE; + } + int32_t dataSize; binder_status_t status = AParcel_readInt32(parcel, &dataSize); @@ -99,7 +120,11 @@ class AParcelableHolder { return STATUS_BAD_VALUE; } +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 31, *)) { +#else + if (__ANDROID_API__ >= 31) { +#endif status = AParcel_appendFrom(parcel, mParcel.get(), dataStartPos, dataSize); } else { status = STATUS_INVALID_OPERATION; @@ -115,7 +140,11 @@ class AParcelableHolder { if (this->mStability > T::_aidl_stability) { return STATUS_BAD_VALUE; } +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 31, *)) { +#else + if (__ANDROID_API__ >= 31) { +#endif AParcel_reset(mParcel.get()); } else { return STATUS_INVALID_OPERATION; @@ -129,7 +158,11 @@ class AParcelableHolder { binder_status_t getParcelable(std::optional<T>* ret) const { const std::string parcelableDesc(T::descriptor); AParcel_setDataPosition(mParcel.get(), 0); +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 31, *)) { +#else + if (__ANDROID_API__ >= 31) { +#endif if (AParcel_getDataSize(mParcel.get()) == 0) { *ret = std::nullopt; return STATUS_OK; @@ -153,7 +186,11 @@ class AParcelableHolder { } void reset() { +#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ if (__builtin_available(android 31, *)) { +#else + if (__ANDROID_API__ >= 31) { +#endif AParcel_reset(mParcel.get()); } } diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h index 2a66941cef..dfa8ea28e7 100644 --- a/libs/binder/ndk/include_platform/android/binder_manager.h +++ b/libs/binder/ndk/include_platform/android/binder_manager.h @@ -53,11 +53,19 @@ __attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const /** * Gets a binder object with this specific instance name. Blocks for a couple of seconds waiting on * it. This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible - * for calling AIBinder_decStrong). + * for calling AIBinder_decStrong). This does polling. A more efficient way to make sure you + * unblock as soon as the service is available is to use AIBinder_waitForService. * * WARNING: when using this API across an APEX boundary, do not use with unstable * AIDL services. TODO(b/139325195) * + * WARNING: when using this API, typically, you should call it in a loop. It's dangerous to + * assume that nullptr could mean that the service is not available. The service could just + * be starting. Generally, whether a service exists, this information should be declared + * externally (for instance, an Android feature might imply the existence of a service, + * a system property, or in the case of services in the VINTF manifest, it can be checked + * with AServiceManager_isDeclared). + * * \param instance identifier of the service used to lookup the service. */ __attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance) diff --git a/libs/binder/rust/src/parcel/parcelable_holder.rs b/libs/binder/rust/src/parcel/parcelable_holder.rs index d58e839ad4..432da5dfd7 100644 --- a/libs/binder/rust/src/parcel/parcelable_holder.rs +++ b/libs/binder/rust/src/parcel/parcelable_holder.rs @@ -233,7 +233,9 @@ impl Parcelable for ParcelableHolder { } fn read_from_parcel(&mut self, parcel: &BorrowedParcel<'_>) -> Result<(), StatusCode> { - self.stability = parcel.read()?; + if self.stability != parcel.read()? { + return Err(StatusCode::BAD_VALUE); + } let data_size: i32 = parcel.read()?; if data_size < 0 { diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index ff55d6ebdc..a3533d831b 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -99,6 +99,7 @@ cc_test { "binderParcelUnitTest.cpp", "binderBinderUnitTest.cpp", "binderStatusUnitTest.cpp", + "binderMemoryHeapBaseUnitTest.cpp", ], shared_libs: [ "libbinder", diff --git a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp new file mode 100644 index 0000000000..21cb70be17 --- /dev/null +++ b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp @@ -0,0 +1,97 @@ +/* + * 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 <binder/MemoryHeapBase.h> +#include <cutils/ashmem.h> +#include <fcntl.h> + +#include <gtest/gtest.h> +using namespace android; +#ifdef __BIONIC__ +TEST(MemoryHeapBase, ForceMemfdRespected) { + auto mHeap = sp<MemoryHeapBase>::make(10, MemoryHeapBase::FORCE_MEMFD, "Test mapping"); + int fd = mHeap->getHeapID(); + EXPECT_NE(fd, -1); + EXPECT_FALSE(ashmem_valid(fd)); + EXPECT_NE(fcntl(fd, F_GET_SEALS), -1); +} + +TEST(MemoryHeapBase, MemfdSealed) { + auto mHeap = sp<MemoryHeapBase>::make(8192, + MemoryHeapBase::FORCE_MEMFD, + "Test mapping"); + int fd = mHeap->getHeapID(); + EXPECT_NE(fd, -1); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL); +} + +TEST(MemoryHeapBase, MemfdUnsealed) { + auto mHeap = sp<MemoryHeapBase>::make(8192, + MemoryHeapBase::FORCE_MEMFD | + MemoryHeapBase::MEMFD_ALLOW_SEALING, + "Test mapping"); + int fd = mHeap->getHeapID(); + EXPECT_NE(fd, -1); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), 0); +} + +TEST(MemoryHeapBase, MemfdSealedProtected) { + auto mHeap = sp<MemoryHeapBase>::make(8192, + MemoryHeapBase::FORCE_MEMFD | + MemoryHeapBase::READ_ONLY, + "Test mapping"); + int fd = mHeap->getHeapID(); + EXPECT_NE(fd, -1); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL | F_SEAL_FUTURE_WRITE); +} + +TEST(MemoryHeapBase, MemfdUnsealedProtected) { + auto mHeap = sp<MemoryHeapBase>::make(8192, + MemoryHeapBase::FORCE_MEMFD | + MemoryHeapBase::READ_ONLY | + MemoryHeapBase::MEMFD_ALLOW_SEALING, + "Test mapping"); + int fd = mHeap->getHeapID(); + EXPECT_NE(fd, -1); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_FUTURE_WRITE); +} + +#else +TEST(MemoryHeapBase, HostMemfdExpected) { + auto mHeap = sp<MemoryHeapBase>::make(8192, + MemoryHeapBase::READ_ONLY, + "Test mapping"); + int fd = mHeap->getHeapID(); + void* ptr = mHeap->getBase(); + EXPECT_NE(ptr, MAP_FAILED); + EXPECT_TRUE(ashmem_valid(fd)); + EXPECT_EQ(mHeap->getFlags(), MemoryHeapBase::READ_ONLY); +} + +TEST(MemoryHeapBase,HostMemfdException) { + auto mHeap = sp<MemoryHeapBase>::make(8192, + MemoryHeapBase::FORCE_MEMFD | + MemoryHeapBase::READ_ONLY | + MemoryHeapBase::MEMFD_ALLOW_SEALING, + "Test mapping"); + int fd = mHeap->getHeapID(); + void* ptr = mHeap->getBase(); + EXPECT_EQ(mHeap->getFlags(), MemoryHeapBase::READ_ONLY); + EXPECT_TRUE(ashmem_valid(fd)); + EXPECT_NE(ptr, MAP_FAILED); +} + +#endif diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp index 38bde3a011..57d496d2fb 100644 --- a/libs/binder/tests/parcel_fuzzer/Android.bp +++ b/libs/binder/tests/parcel_fuzzer/Android.bp @@ -66,10 +66,13 @@ cc_library_static { srcs: [ "random_fd.cpp", "random_parcel.cpp", + "libbinder_driver.cpp", + "libbinder_ndk_driver.cpp", ], shared_libs: [ "libbase", "libbinder", + "libbinder_ndk", "libcutils", "libutils", ], diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h new file mode 100644 index 0000000000..a9a6197439 --- /dev/null +++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <binder/IBinder.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { +/** + * Based on the random data in provider, construct an arbitrary number of + * Parcel objects and send them to the service in serial. + * + * Usage: + * + * extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + * FuzzedDataProvider provider = FuzzedDataProvider(data, size); + * // can use provider here to create a service with different options + * sp<IFoo> myService = sp<IFoo>::make(...); + * fuzzService(myService, std::move(provider)); + * } + */ +void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider); +} // namespace android diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h new file mode 100644 index 0000000000..f2b782337c --- /dev/null +++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <android/binder_parcel.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { +/** + * Based on the random data in provider, construct an arbitrary number of + * Parcel objects and send them to the service in serial. + * + * Usage: + * + * extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + * FuzzedDataProvider provider = FuzzedDataProvider(data, size); + * // can use provider here to create a service with different options + * std::shared_ptr<IFoo> myService = ndk::SharedRefBase<IFoo>::make(...); + * fuzzService(myService->asBinder().get(), std::move(provider)); + * } + */ +void fuzzService(AIBinder* binder, FuzzedDataProvider&& provider); +} // namespace android diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp new file mode 100644 index 0000000000..e849c9bbce --- /dev/null +++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <fuzzbinder/libbinder_driver.h> + +#include <fuzzbinder/random_parcel.h> + +namespace android { + +void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider) { + while (provider.remaining_bytes() > 0) { + uint32_t code = provider.ConsumeIntegral<uint32_t>(); + uint32_t flags = provider.ConsumeIntegral<uint32_t>(); + Parcel data; + + std::vector<uint8_t> subData = provider.ConsumeBytes<uint8_t>( + provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes())); + fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size())); + + Parcel reply; + (void)binder->transact(code, data, &reply, flags); + } +} + +} // namespace android diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp new file mode 100644 index 0000000000..462ef9a5e9 --- /dev/null +++ b/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <fuzzbinder/libbinder_ndk_driver.h> + +#include <fuzzbinder/libbinder_driver.h> +#include <fuzzbinder/random_parcel.h> + +// libbinder_ndk doesn't export this header which breaks down its API for NDK +// and APEX users, but we need access to it to fuzz. +#include "../../ndk/ibinder_internal.h" + +namespace android { + +void fuzzService(AIBinder* binder, FuzzedDataProvider&& provider) { + fuzzService(binder->getBinder(), std::move(provider)); +} + +} // namespace android diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp index 1513ecafc8..45a6d47bb4 100644 --- a/libs/cputimeinstate/testtimeinstate.cpp +++ b/libs/cputimeinstate/testtimeinstate.cpp @@ -31,6 +31,7 @@ #include <android-base/unique_fd.h> #include <bpf/BpfMap.h> #include <cputimeinstate.h> +#include <cutils/android_filesystem_config.h> #include <libbpf.h> namespace android { @@ -219,6 +220,7 @@ TEST_F(TimeInStateTest, TotalAndAllUidTimeInStateConsistent) { uint32_t totalFreqsCount = totalTimes.size(); std::vector<uint64_t> allUidTimes(totalFreqsCount, 0); for (auto const &[uid, uidTimes]: *allUid) { + if (uid == AID_SDK_SANDBOX) continue; for (uint32_t freqIdx = 0; freqIdx < uidTimes[policyIdx].size(); ++freqIdx) { allUidTimes[std::min(freqIdx, totalFreqsCount - 1)] += uidTimes[policyIdx][freqIdx]; } @@ -646,5 +648,55 @@ TEST_F(TimeInStateTest, GetAggregatedTaskCpuFreqTimes) { } } +void *forceSwitchWithUid(void *uidPtr) { + if (!uidPtr) return nullptr; + setuid(*(uint32_t *)uidPtr); + + // Sleep briefly to trigger a context switch, ensuring we see at least one update. + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 1000000; + nanosleep(&ts, NULL); + return nullptr; +} + +TEST_F(TimeInStateTest, SdkSandboxUid) { + // Find an unused app UID and its corresponding SDK sandbox uid. + uint32_t appUid = AID_APP_START, sandboxUid; + { + auto times = getUidsCpuFreqTimes(); + ASSERT_TRUE(times.has_value()); + ASSERT_FALSE(times->empty()); + for (const auto &kv : *times) { + if (kv.first > AID_APP_END) break; + appUid = std::max(appUid, kv.first); + } + appUid++; + sandboxUid = appUid + (AID_SDK_SANDBOX_PROCESS_START - AID_APP_START); + } + + // Create a thread to run with the fake sandbox uid. + pthread_t thread; + ASSERT_EQ(pthread_create(&thread, NULL, &forceSwitchWithUid, &sandboxUid), 0); + pthread_join(thread, NULL); + + // Confirm we recorded stats for appUid and AID_SDK_SANDBOX but not sandboxUid + auto allTimes = getUidsCpuFreqTimes(); + ASSERT_TRUE(allTimes.has_value()); + ASSERT_FALSE(allTimes->empty()); + ASSERT_NE(allTimes->find(appUid), allTimes->end()); + ASSERT_NE(allTimes->find(AID_SDK_SANDBOX), allTimes->end()); + ASSERT_EQ(allTimes->find(sandboxUid), allTimes->end()); + + auto allConcurrentTimes = getUidsConcurrentTimes(); + ASSERT_TRUE(allConcurrentTimes.has_value()); + ASSERT_FALSE(allConcurrentTimes->empty()); + ASSERT_NE(allConcurrentTimes->find(appUid), allConcurrentTimes->end()); + ASSERT_NE(allConcurrentTimes->find(AID_SDK_SANDBOX), allConcurrentTimes->end()); + ASSERT_EQ(allConcurrentTimes->find(sandboxUid), allConcurrentTimes->end()); + + ASSERT_TRUE(clearUidTimes(appUid)); +} + } // namespace bpf } // namespace android diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp index a8a847664f..de7d8f879b 100644 --- a/libs/vr/libvrflinger/vr_flinger.cpp +++ b/libs/vr/libvrflinger/vr_flinger.cpp @@ -17,6 +17,7 @@ #include <processgroup/sched_policy.h> #include <sys/prctl.h> #include <sys/resource.h> +#include <utils/ThreadDefs.h> #include <functional> diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp index df4db199f8..455a1e2133 100644 --- a/services/inputflinger/tests/fuzzers/Android.bp +++ b/services/inputflinger/tests/fuzzers/Android.bp @@ -42,4 +42,7 @@ cc_fuzz { srcs: [ "LatencyTrackerFuzzer.cpp", ], + fuzz_config: { + cc: ["android-framework-input@google.com"], + }, } diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index cf774fd9b8..0c5d61b8d5 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -624,8 +624,10 @@ void CreateInfoWrapper::FilterExtension(const char* name) { switch (ext_bit) { case ProcHook::KHR_android_surface: case ProcHook::KHR_surface: + case ProcHook::KHR_surface_protected_capabilities: case ProcHook::EXT_swapchain_colorspace: case ProcHook::KHR_get_surface_capabilities2: + case ProcHook::GOOGLE_surfaceless_query: hook_extensions_.set(ext_bit); // return now as these extensions do not require HAL support return; @@ -701,8 +703,10 @@ void CreateInfoWrapper::FilterExtension(const char* name) { case ProcHook::KHR_external_fence_capabilities: case ProcHook::KHR_get_surface_capabilities2: case ProcHook::KHR_surface: + case ProcHook::KHR_surface_protected_capabilities: case ProcHook::EXT_debug_report: case ProcHook::EXT_swapchain_colorspace: + case ProcHook::GOOGLE_surfaceless_query: case ProcHook::ANDROID_native_buffer: case ProcHook::EXTENSION_CORE_1_0: case ProcHook::EXTENSION_CORE_1_1: @@ -913,6 +917,9 @@ VkResult EnumerateInstanceExtensionProperties( loader_extensions.push_back({ VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION}); + loader_extensions.push_back( + {VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME, + VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION}); loader_extensions.push_back({ VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_SPEC_VERSION}); @@ -922,6 +929,8 @@ VkResult EnumerateInstanceExtensionProperties( loader_extensions.push_back({ VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION}); + loader_extensions.push_back({VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME, + VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION}); static const VkExtensionProperties loader_debug_report_extension = { VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION, diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp index 5f37a50a03..b436db1de7 100644 --- a/vulkan/libvulkan/driver_gen.cpp +++ b/vulkan/libvulkan/driver_gen.cpp @@ -565,11 +565,13 @@ ProcHook::Extension GetProcHookExtension(const char* name) { if (strcmp(name, "VK_EXT_hdr_metadata") == 0) return ProcHook::EXT_hdr_metadata; if (strcmp(name, "VK_EXT_swapchain_colorspace") == 0) return ProcHook::EXT_swapchain_colorspace; if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing; + if (strcmp(name, "VK_GOOGLE_surfaceless_query") == 0) return ProcHook::GOOGLE_surfaceless_query; if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface; if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2; if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present; if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image; if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface; + if (strcmp(name, "VK_KHR_surface_protected_capabilities") == 0) return ProcHook::KHR_surface_protected_capabilities; if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain; if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer; if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2; diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h index 047e774004..688630c0a5 100644 --- a/vulkan/libvulkan/driver_gen.h +++ b/vulkan/libvulkan/driver_gen.h @@ -41,11 +41,13 @@ struct ProcHook { EXT_hdr_metadata, EXT_swapchain_colorspace, GOOGLE_display_timing, + GOOGLE_surfaceless_query, KHR_android_surface, KHR_get_surface_capabilities2, KHR_incremental_present, KHR_shared_presentable_image, KHR_surface, + KHR_surface_protected_capabilities, KHR_swapchain, ANDROID_external_memory_android_hardware_buffer, KHR_bind_memory2, diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index 6191063894..ec673123b0 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -614,42 +614,65 @@ VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/, VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR( - VkPhysicalDevice /*pdev*/, + VkPhysicalDevice pdev, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* capabilities) { ATRACE_CALL(); int err; - ANativeWindow* window = SurfaceFromHandle(surface)->window.get(); - int width, height; - err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width); - if (err != android::OK) { - ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", - strerror(-err), err); - return VK_ERROR_SURFACE_LOST_KHR; - } - err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height); - if (err != android::OK) { - ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", - strerror(-err), err); - return VK_ERROR_SURFACE_LOST_KHR; - } - int transform_hint; - err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint); - if (err != android::OK) { - ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)", - strerror(-err), err); - return VK_ERROR_SURFACE_LOST_KHR; - } - int max_buffer_count; - err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &max_buffer_count); - if (err != android::OK) { - ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)", - strerror(-err), err); - return VK_ERROR_SURFACE_LOST_KHR; + if (surface == VK_NULL_HANDLE) { + const InstanceData& instance_data = GetData(pdev); + ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query; + bool surfaceless_enabled = + instance_data.hook_extensions.test(surfaceless); + if (!surfaceless_enabled) { + // It is an error to pass a surface==VK_NULL_HANDLE unless the + // VK_GOOGLE_surfaceless_query extension is enabled + return VK_ERROR_SURFACE_LOST_KHR; + } + // Support for VK_GOOGLE_surfaceless_query. The primary purpose of this + // extension for this function is for + // 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; + } else { + ANativeWindow* window = SurfaceFromHandle(surface)->window.get(); + + err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width); + if (err != android::OK) { + ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", + strerror(-err), err); + return VK_ERROR_SURFACE_LOST_KHR; + } + err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height); + if (err != android::OK) { + ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)", + strerror(-err), err); + return VK_ERROR_SURFACE_LOST_KHR; + } + + err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, + &transform_hint); + if (err != android::OK) { + ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)", + strerror(-err), err); + return VK_ERROR_SURFACE_LOST_KHR; + } + + err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, + &max_buffer_count); + if (err != android::OK) { + ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)", + 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); @@ -690,23 +713,43 @@ VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, const InstanceData& instance_data = GetData(pdev); bool wide_color_support = false; - Surface& surface = *SurfaceFromHandle(surface_handle); - int err = native_window_get_wide_color_support(surface.window.get(), - &wide_color_support); - if (err) { - return VK_ERROR_SURFACE_LOST_KHR; - } - ALOGV("wide_color_support is: %d", wide_color_support); - wide_color_support = - wide_color_support && + uint64_t consumer_usage = 0; + bool swapchain_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace); + if (surface_handle == VK_NULL_HANDLE) { + ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query; + bool surfaceless_enabled = + instance_data.hook_extensions.test(surfaceless); + if (!surfaceless_enabled) { + return VK_ERROR_SURFACE_LOST_KHR; + } + // Support for VK_GOOGLE_surfaceless_query. The EGL loader + // unconditionally supports wide color formats, even if they will cause + // a SurfaceFlinger fallback. Based on that, wide_color_support will be + // set to true in this case. + wide_color_support = true; + + // TODO(b/203826952): research proper value; temporarily use the + // values seen on Pixel + consumer_usage = AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY; + } else { + Surface& surface = *SurfaceFromHandle(surface_handle); + int err = native_window_get_wide_color_support(surface.window.get(), + &wide_color_support); + if (err) { + return VK_ERROR_SURFACE_LOST_KHR; + } + ALOGV("wide_color_support is: %d", wide_color_support); + + consumer_usage = surface.consumer_usage; + } + wide_color_support = wide_color_support && swapchain_ext; AHardwareBuffer_Desc desc = {}; desc.width = 1; desc.height = 1; desc.layers = 1; - desc.usage = surface.consumer_usage | - AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | + desc.usage = consumer_usage | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER; // We must support R8G8B8A8 @@ -721,6 +764,10 @@ VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT}); } + // NOTE: Any new formats that are added must be coordinated across different + // Android users. This includes the ANGLE team (a layered implementation of + // OpenGL-ES). + desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM; if (AHardwareBuffer_isSupported(&desc)) { all_formats.emplace_back(VkSurfaceFormatKHR{ @@ -753,6 +800,10 @@ VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, } } + // NOTE: Any new formats that are added must be coordinated across different + // Android users. This includes the ANGLE team (a layered implementation of + // OpenGL-ES). + VkResult result = VK_SUCCESS; if (formats) { uint32_t transfer_count = all_formats.size(); @@ -797,6 +848,12 @@ VkResult GetPhysicalDeviceSurfaceCapabilities2KHR( .supportedUsageFlags; } break; + case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: { + VkSurfaceProtectedCapabilitiesKHR* protected_caps = + reinterpret_cast<VkSurfaceProtectedCapabilitiesKHR*>(caps); + protected_caps->supportsProtected = VK_TRUE; + } break; + default: // Ignore all other extension structs break; @@ -848,31 +905,51 @@ VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, int err; int query_value; - ANativeWindow* window = SurfaceFromHandle(surface)->window.get(); + std::vector<VkPresentModeKHR> present_modes; + if (surface == VK_NULL_HANDLE) { + const InstanceData& instance_data = GetData(pdev); + ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query; + bool surfaceless_enabled = + instance_data.hook_extensions.test(surfaceless); + if (!surfaceless_enabled) { + return VK_ERROR_SURFACE_LOST_KHR; + } + // Support for VK_GOOGLE_surfaceless_query. The primary purpose of this + // extension for this function is for + // VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR and + // VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR. We technically cannot + // know if VK_PRESENT_MODE_SHARED_MAILBOX_KHR is supported without a + // surface, and that cannot be relied upon. + present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR); + present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR); + } else { + ANativeWindow* window = SurfaceFromHandle(surface)->window.get(); - err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, - &query_value); - if (err != android::OK || query_value < 0) { - ALOGE( - "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) " - "value=%d", - strerror(-err), err, query_value); - return VK_ERROR_SURFACE_LOST_KHR; - } - uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value); + err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, + &query_value); + if (err != android::OK || query_value < 0) { + ALOGE( + "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) " + "value=%d", + strerror(-err), err, query_value); + return VK_ERROR_SURFACE_LOST_KHR; + } + uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value); + + err = + window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value); + if (err != android::OK || query_value < 0) { + ALOGE( + "NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d", + strerror(-err), err, query_value); + return VK_ERROR_SURFACE_LOST_KHR; + } + uint32_t max_buffer_count = static_cast<uint32_t>(query_value); - err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value); - if (err != android::OK || query_value < 0) { - ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d", - strerror(-err), err, query_value); - return VK_ERROR_SURFACE_LOST_KHR; + if (min_undequeued_buffers + 1 < max_buffer_count) + present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR); + present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR); } - uint32_t max_buffer_count = static_cast<uint32_t>(query_value); - - std::vector<VkPresentModeKHR> present_modes; - if (min_undequeued_buffers + 1 < max_buffer_count) - present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR); - present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR); VkPhysicalDevicePresentationPropertiesANDROID present_properties; QueryPresentationProperties(pdev, &present_properties); diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py index 6a73023193..af56764a21 100644 --- a/vulkan/scripts/driver_generator.py +++ b/vulkan/scripts/driver_generator.py @@ -27,11 +27,13 @@ _INTERCEPTED_EXTENSIONS = [ 'VK_EXT_hdr_metadata', 'VK_EXT_swapchain_colorspace', 'VK_GOOGLE_display_timing', + 'VK_GOOGLE_surfaceless_query', 'VK_KHR_android_surface', 'VK_KHR_get_surface_capabilities2', 'VK_KHR_incremental_present', 'VK_KHR_shared_presentable_image', 'VK_KHR_surface', + 'VK_KHR_surface_protected_capabilities', 'VK_KHR_swapchain', ] |