Merge "Add linkToDeath support for RPC binder so a client can act on disconnect"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f759674..6dea91b 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1508,7 +1508,6 @@
     dprintf(out_fd, "========================================================\n");
 
     RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
-    RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}, out_fd);
     RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
     RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
     RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
diff --git a/libs/adbd_auth/libadbd_auth.map.txt b/libs/adbd_auth/libadbd_auth.map.txt
index 7584ca3..f9f042e 100644
--- a/libs/adbd_auth/libadbd_auth.map.txt
+++ b/libs/adbd_auth/libadbd_auth.map.txt
@@ -1,17 +1,17 @@
 LIBADBD_AUTH {
   global:
-    adbd_auth_new; # apex introduced=30
-    adbd_auth_delete; # apex introduced=30
-    adbd_auth_run; # apex introduced=30
-    adbd_auth_get_public_keys; #apex introduced=30
-    adbd_auth_notify_auth; # apex introduced=30
-    adbd_auth_notify_disconnect; # apex introduced=30
-    adbd_auth_prompt_user; # apex introduced=30
-    adbd_auth_prompt_user_with_id; # apex introduced=30
-    adbd_auth_tls_device_connected; # apex introduced=30
-    adbd_auth_tls_device_disconnected; # apex introduced=30
-    adbd_auth_get_max_version; # apex introduced=30
-    adbd_auth_supports_feature; # apex introduced=30
+    adbd_auth_new; # systemapi introduced=30
+    adbd_auth_delete; # systemapi introduced=30
+    adbd_auth_run; # systemapi introduced=30
+    adbd_auth_get_public_keys; # systemapi introduced=30
+    adbd_auth_notify_auth; # systemapi introduced=30
+    adbd_auth_notify_disconnect; # systemapi introduced=30
+    adbd_auth_prompt_user; # systemapi introduced=30
+    adbd_auth_prompt_user_with_id; # systemapi introduced=30
+    adbd_auth_tls_device_connected; # systemapi introduced=30
+    adbd_auth_tls_device_disconnected; # systemapi introduced=30
+    adbd_auth_get_max_version; # systemapi introduced=30
+    adbd_auth_supports_feature; # systemapi introduced=30
   local:
     *;
 };
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d536219..b50cfb3 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -972,18 +972,15 @@
                             freeBuffer);
                     } else {
                         err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
-                        freeBuffer(nullptr,
-                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
-                            tr.data_size,
-                            reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
-                            tr.offsets_size/sizeof(binder_size_t));
+                        freeBuffer(reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
+                                   tr.data_size,
+                                   reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
+                                   tr.offsets_size / sizeof(binder_size_t));
                     }
                 } else {
-                    freeBuffer(nullptr,
-                        reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
-                        tr.data_size,
-                        reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
-                        tr.offsets_size/sizeof(binder_size_t));
+                    freeBuffer(reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size,
+                               reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
+                               tr.offsets_size / sizeof(binder_size_t));
                     continue;
                 }
             }
@@ -1473,17 +1470,13 @@
              ee.id, ee.command, ee.param);
 }
 
-void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data,
-                                size_t /*dataSize*/,
-                                const binder_size_t* /*objects*/,
-                                size_t /*objectsSize*/)
-{
+void IPCThreadState::freeBuffer(const uint8_t* data, size_t /*dataSize*/,
+                                const binder_size_t* /*objects*/, size_t /*objectsSize*/) {
     //ALOGI("Freeing parcel %p", &parcel);
     IF_LOG_COMMANDS() {
         alog << "Writing BC_FREE_BUFFER for " << data << endl;
     }
     ALOG_ASSERT(data != NULL, "Called with NULL data");
-    if (parcel != nullptr) parcel->closeFileDescriptors();
     IPCThreadState* state = self();
     state->mOut.writeInt32(BC_FREE_BUFFER);
     state->mOut.writePointer((uintptr_t)data);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 537527e..8b5d118 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2590,6 +2590,22 @@
 
     LOG_ALWAYS_FATAL_IF(session == nullptr);
 
+    if (objectTableSize != ancillaryFds.size()) {
+        ALOGE("objectTableSize=%zu ancillaryFds.size=%zu", objectTableSize, ancillaryFds.size());
+        relFunc(data, dataSize, nullptr, 0);
+        return BAD_VALUE;
+    }
+    for (size_t i = 0; i < objectTableSize; i++) {
+        uint32_t minObjectEnd;
+        if (__builtin_add_overflow(objectTable[i], sizeof(RpcFields::ObjectType), &minObjectEnd) ||
+            minObjectEnd >= dataSize) {
+            ALOGE("received out of range object position: %" PRIu32 " (parcel size is %zu)",
+                  objectTable[i], dataSize);
+            relFunc(data, dataSize, nullptr, 0);
+            return BAD_VALUE;
+        }
+    }
+
     freeData();
     markForRpc(session);
 
@@ -2600,12 +2616,6 @@
     mDataSize = mDataCapacity = dataSize;
     mOwner = relFunc;
 
-    if (objectTableSize != ancillaryFds.size()) {
-        ALOGE("objectTableSize=%zu ancillaryFds.size=%zu", objectTableSize, ancillaryFds.size());
-        freeData(); // don't leak mData
-        return BAD_VALUE;
-    }
-
     rpcFields->mObjectPositions.reserve(objectTableSize);
     for (size_t i = 0; i < objectTableSize; i++) {
         rpcFields->mObjectPositions.push_back(objectTable[i]);
@@ -2706,7 +2716,9 @@
         LOG_ALLOC("Parcel %p: freeing other owner data", this);
         //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
         auto* kernelFields = maybeKernelFields();
-        mOwner(this, mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr,
+        // Close FDs before freeing, otherwise they will leak for kernel binder.
+        closeFileDescriptors();
+        mOwner(mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr,
                kernelFields ? kernelFields->mObjectsSize : 0);
     } else {
         LOG_ALLOC("Parcel %p: freeing allocated data", this);
@@ -2891,8 +2903,13 @@
         if (objects && kernelFields && kernelFields->mObjects) {
             memcpy(objects, kernelFields->mObjects, objectsSize * sizeof(binder_size_t));
         }
-        //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
-        mOwner(this, mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr,
+        // ALOGI("Freeing data ref of %p (pid=%d)", this, getpid());
+        if (kernelFields) {
+            // TODO(b/239222407): This seems wrong. We should only free FDs when
+            // they are in a truncated section of the parcel.
+            closeFileDescriptors();
+        }
+        mOwner(mData, mDataSize, kernelFields ? kernelFields->mObjects : nullptr,
                kernelFields ? kernelFields->mObjectsSize : 0);
         mOwner = nullptr;
 
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index e3ff64d..c0e36c4 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -268,33 +268,31 @@
                             "New state should be impossible after terminating!");
         return;
     }
+    mTerminated = true;
 
     if (SHOULD_LOG_RPC_DETAIL) {
         ALOGE("RpcState::clear()");
         dumpLocked();
     }
 
-    // if the destructor of a binder object makes another RPC call, then calling
-    // decStrong could deadlock. So, we must hold onto these binders until
-    // mNodeMutex is no longer taken.
-    std::vector<sp<IBinder>> tempHoldBinder;
-
-    mTerminated = true;
+    // invariants
     for (auto& [address, node] : mNodeForAddress) {
-        sp<IBinder> binder = node.binder.promote();
-        LOG_ALWAYS_FATAL_IF(binder == nullptr,
-                            "Binder expected to be owned with address: %" PRIu64 " %s", address,
-                            node.toString().c_str());
-
-        if (node.sentRef != nullptr) {
-            tempHoldBinder.push_back(node.sentRef);
+        bool guaranteedHaveBinder = node.timesSent > 0;
+        if (guaranteedHaveBinder) {
+            LOG_ALWAYS_FATAL_IF(node.sentRef == nullptr,
+                                "Binder expected to be owned with address: %" PRIu64 " %s", address,
+                                node.toString().c_str());
         }
     }
 
-    mNodeForAddress.clear();
+    // if the destructor of a binder object makes another RPC call, then calling
+    // decStrong could deadlock. So, we must hold onto these binders until
+    // mNodeMutex is no longer taken.
+    auto temp = std::move(mNodeForAddress);
+    mNodeForAddress.clear(); // RpcState isn't reusable, but for future/explicit
 
     _l.unlock();
-    tempHoldBinder.clear(); // explicit
+    temp.clear(); // explicit
 }
 
 void RpcState::dumpLocked() {
@@ -610,13 +608,12 @@
     return waitForReply(connection, session, reply);
 }
 
-static void cleanup_reply_data(Parcel* p, const uint8_t* data, size_t dataSize,
-                               const binder_size_t* objects, size_t objectsCount) {
-    (void)p;
+static void cleanup_reply_data(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
+                               size_t objectsCount) {
     delete[] const_cast<uint8_t*>(data);
     (void)dataSize;
     LOG_ALWAYS_FATAL_IF(objects != nullptr);
-    LOG_ALWAYS_FATAL_IF(objectsCount != 0, "%zu objects remaining", objectsCount);
+    (void)objectsCount;
 }
 
 status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection,
@@ -672,14 +669,21 @@
     Span<const uint32_t> objectTableSpan;
     if (session->getProtocolVersion().value() >=
         RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE) {
-        Span<const uint8_t> objectTableBytes = parcelSpan.splitOff(rpcReply.parcelDataSize);
+        std::optional<Span<const uint8_t>> objectTableBytes =
+                parcelSpan.splitOff(rpcReply.parcelDataSize);
+        if (!objectTableBytes.has_value()) {
+            ALOGE("Parcel size larger than available bytes: %" PRId32 " vs %zu. Terminating!",
+                  rpcReply.parcelDataSize, parcelSpan.byteSize());
+            (void)session->shutdownAndWait(false);
+            return BAD_VALUE;
+        }
         std::optional<Span<const uint32_t>> maybeSpan =
-                objectTableBytes.reinterpret<const uint32_t>();
+                objectTableBytes->reinterpret<const uint32_t>();
         if (!maybeSpan.has_value()) {
             ALOGE("Bad object table size inferred from RpcWireReply. Saw bodySize=%" PRId32
                   " sizeofHeader=%zu parcelSize=%" PRId32 " objectTableBytesSize=%zu. Terminating!",
                   command.bodySize, rpcReplyWireSize, rpcReply.parcelDataSize,
-                  objectTableBytes.size);
+                  objectTableBytes->size);
             return BAD_VALUE;
         }
         objectTableSpan = *maybeSpan;
@@ -816,9 +820,8 @@
                                    std::move(ancillaryFds));
 }
 
-static void do_nothing_to_transact_data(Parcel* p, const uint8_t* data, size_t dataSize,
+static void do_nothing_to_transact_data(const uint8_t* data, size_t dataSize,
                                         const binder_size_t* objects, size_t objectsCount) {
-    (void)p;
     (void)data;
     (void)dataSize;
     (void)objects;
@@ -922,15 +925,22 @@
         Span<const uint32_t> objectTableSpan;
         if (session->getProtocolVersion().value() >
             RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE) {
-            Span<const uint8_t> objectTableBytes = parcelSpan.splitOff(transaction->parcelDataSize);
+            std::optional<Span<const uint8_t>> objectTableBytes =
+                    parcelSpan.splitOff(transaction->parcelDataSize);
+            if (!objectTableBytes.has_value()) {
+                ALOGE("Parcel size (%" PRId32 ") greater than available bytes (%zu). Terminating!",
+                      transaction->parcelDataSize, parcelSpan.byteSize());
+                (void)session->shutdownAndWait(false);
+                return BAD_VALUE;
+            }
             std::optional<Span<const uint32_t>> maybeSpan =
-                    objectTableBytes.reinterpret<const uint32_t>();
+                    objectTableBytes->reinterpret<const uint32_t>();
             if (!maybeSpan.has_value()) {
                 ALOGE("Bad object table size inferred from RpcWireTransaction. Saw bodySize=%zu "
                       "sizeofHeader=%zu parcelSize=%" PRId32
                       " objectTableBytesSize=%zu. Terminating!",
                       transactionData.size(), sizeof(RpcWireTransaction),
-                      transaction->parcelDataSize, objectTableBytes.size);
+                      transaction->parcelDataSize, objectTableBytes->size);
                 return BAD_VALUE;
             }
             objectTableSpan = *maybeSpan;
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
index 7c6d6f1..e04199c 100644
--- a/libs/binder/Utils.h
+++ b/libs/binder/Utils.h
@@ -48,9 +48,11 @@
     // Truncates `this` to a length of `offset` and returns a span with the
     // remainder.
     //
-    // Aborts if offset > size.
-    Span<T> splitOff(size_t offset) {
-        LOG_ALWAYS_FATAL_IF(offset > size);
+    // `std::nullopt` iff offset > size.
+    std::optional<Span<T>> splitOff(size_t offset) {
+        if (offset > size) {
+            return std::nullopt;
+        }
         Span<T> rest = {data + offset, size - offset};
         size = offset;
         return rest;
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 8ce3bc9..c01e92f 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -217,9 +217,8 @@
             void                clearCaller();
 
     static  void                threadDestructor(void *st);
-    static  void                freeBuffer(Parcel* parcel,
-                                           const uint8_t* data, size_t dataSize,
-                                           const binder_size_t* objects, size_t objectsSize);
+    static void freeBuffer(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
+                           size_t objectsSize);
     static  void                logExtendedError();
 
     const   sp<ProcessState>    mProcess;
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 91febbd..5469239 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -598,9 +598,9 @@
     void                print(TextOutput& to, uint32_t flags = 0) const;
 
 private:
-    typedef void        (*release_func)(Parcel* parcel,
-                                        const uint8_t* data, size_t dataSize,
-                                        const binder_size_t* objects, size_t objectsSize);
+    // `objects` and `objectsSize` always 0 for RPC Parcels.
+    typedef void (*release_func)(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
+                                 size_t objectsSize);
 
     uintptr_t           ipcData() const;
     size_t              ipcDataSize() const;
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index f3f2886..6bc9814 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -89,12 +89,12 @@
     AStatus_getStatus;
     AStatus_isOk;
     AStatus_newOk;
-    ABinderProcess_joinThreadPool; # apex llndk
-    ABinderProcess_setThreadPoolMaxThreadCount; # apex llndk
-    ABinderProcess_startThreadPool; # apex llndk
-    AServiceManager_addService; # apex llndk
-    AServiceManager_checkService; # apex llndk
-    AServiceManager_getService; # apex llndk
+    ABinderProcess_joinThreadPool; # systemapi llndk
+    ABinderProcess_setThreadPoolMaxThreadCount; # systemapi llndk
+    ABinderProcess_startThreadPool; # systemapi llndk
+    AServiceManager_addService; # systemapi llndk
+    AServiceManager_checkService; # systemapi llndk
+    AServiceManager_getService; # systemapi llndk
 };
 
 LIBBINDER_NDK30 { # introduced=30
@@ -105,30 +105,30 @@
     AStatus_deleteDescription;
     AParcel_fromJavaParcel;
 
-    AIBinder_markSystemStability; # apex
+    AIBinder_markSystemStability; # systemapi
     AIBinder_markVendorStability; # llndk
-    AIBinder_markVintfStability; # apex llndk
-    AIBinder_Class_setHandleShellCommand; # apex llndk
+    AIBinder_markVintfStability; # systemapi llndk
+    AIBinder_Class_setHandleShellCommand; # systemapi llndk
 };
 
 LIBBINDER_NDK31 { # introduced=31
   global:
-    ABinderProcess_handlePolledCommands; # apex
-    ABinderProcess_setupPolling; # apex
-    AIBinder_getCallingSid; # apex
-    AIBinder_setRequestingSid; # apex
+    ABinderProcess_handlePolledCommands; # systemapi
+    ABinderProcess_setupPolling; # systemapi
+    AIBinder_getCallingSid; # systemapi
+    AIBinder_setRequestingSid; # systemapi
     AParcel_markSensitive; # systemapi llndk
-    AServiceManager_forEachDeclaredInstance; # apex llndk
-    AServiceManager_forceLazyServicesPersist; # apex llndk
-    AServiceManager_isDeclared; # apex llndk
-    AServiceManager_isUpdatableViaApex; # apex
+    AServiceManager_forEachDeclaredInstance; # systemapi llndk
+    AServiceManager_forceLazyServicesPersist; # systemapi llndk
+    AServiceManager_isDeclared; # systemapi llndk
+    AServiceManager_isUpdatableViaApex; # systemapi
     AServiceManager_reRegister; # llndk
-    AServiceManager_registerLazyService; # apex llndk
+    AServiceManager_registerLazyService; # systemapi llndk
     AServiceManager_setActiveServicesCallback; # llndk
     AServiceManager_tryUnregister; # llndk
-    AServiceManager_waitForService; # apex llndk
+    AServiceManager_waitForService; # systemapi llndk
 
-    AIBinder_forceDowngradeToSystemStability; # apex
+    AIBinder_forceDowngradeToSystemStability; # systemapi
     AIBinder_forceDowngradeToVendorStability; # llndk
 
     AIBinder_Class_getDescriptor;
@@ -146,8 +146,8 @@
     AIBinder_Class_disableInterfaceTokenHeader;
     AIBinder_DeathRecipient_setOnUnlinked;
     AIBinder_isHandlingTransaction;
-    AIBinder_setInheritRt; # apex llndk
-    AIBinder_setMinSchedulerPolicy; # apex llndk
+    AIBinder_setInheritRt; # systemapi llndk
+    AIBinder_setMinSchedulerPolicy; # systemapi llndk
     AParcel_marshal;
     AParcel_unmarshal;
 };
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index f6ab667..501a604 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1029,13 +1029,6 @@
                 // since this session has an incoming connection w/ a threadpool, we
                 // need to manually shut it down
                 EXPECT_TRUE(proc.proc.sessions.at(0).session->shutdownAndWait(true));
-
-                proc.proc.host.setCustomExitStatusCheck([](int wstatus) {
-                    // Flaky. Sometimes gets SIGABRT.
-                    EXPECT_TRUE((WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) ||
-                                (WIFSIGNALED(wstatus) && WTERMSIG(wstatus) == SIGABRT))
-                            << "server process failed: " << WaitStatusToString(wstatus);
-                });
                 proc.expectAlreadyShutdown = true;
             }
         }
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
index 843b6e3..6ea9708 100644
--- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
@@ -19,10 +19,14 @@
 #include <android-base/unique_fd.h>
 #include <fuzzer/FuzzedDataProvider.h>
 
+#include <vector>
+
 namespace android {
 
 // always valid or aborts
 // get a random FD for use in fuzzing, of a few different specific types
-base::unique_fd getRandomFd(FuzzedDataProvider* provider);
+//
+// may return multiple FDs (e.g. pipe), but will always return at least one
+std::vector<base::unique_fd> getRandomFds(FuzzedDataProvider* provider);
 
 } // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
index 459fb12..27587a9 100644
--- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
@@ -33,10 +33,13 @@
 /**
  * Fill parcel data, including some random binder objects and FDs
  *
+ * May insert additional FDs/binders if they own data related to the Parcel (e.g. the other
+ * end of a pipe).
+ *
  * p - the Parcel to fill
  * provider - takes ownership and completely consumes provider
  * writeHeader - optional function to write a specific header once the format of the parcel is
  *     picked (for instance, to write an interface header)
  */
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, const RandomParcelOptions& = {});
+void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOptions* options);
 } // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
index d5aa353..32494e3 100644
--- a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
@@ -44,7 +44,7 @@
 
         std::vector<uint8_t> subData = provider.ConsumeBytes<uint8_t>(
                 provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));
-        fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size()), options);
+        fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size()), &options);
 
         Parcel reply;
         (void)target->transact(code, data, &reply, flags);
diff --git a/libs/binder/tests/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp
index 180a177..bef4ab6 100644
--- a/libs/binder/tests/parcel_fuzzer/main.cpp
+++ b/libs/binder/tests/parcel_fuzzer/main.cpp
@@ -35,17 +35,22 @@
 #include <sys/time.h>
 
 using android::fillRandomParcel;
+using android::RandomParcelOptions;
 using android::sp;
 using android::base::HexString;
 
-void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider) {
+void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider,
+                      RandomParcelOptions* options) {
     // TODO: functionality to create random parcels for libhwbinder parcels
+    (void)options;
+
     std::vector<uint8_t> input = provider.ConsumeRemainingBytes<uint8_t>();
     p->setData(input.data(), input.size());
 }
-static void fillRandomParcel(NdkParcelAdapter* p, FuzzedDataProvider&& provider) {
+static void fillRandomParcel(NdkParcelAdapter* p, FuzzedDataProvider&& provider,
+                             RandomParcelOptions* options) {
     // fill underlying parcel using functions to fill random libbinder parcel
-    fillRandomParcel(p->parcel(), std::move(provider));
+    fillRandomParcel(p->parcel(), std::move(provider), options);
 }
 
 template <typename P, typename B>
@@ -55,9 +60,11 @@
 
     FUZZ_LOG() << "backend: " << backend;
 
+    RandomParcelOptions options;
+
     P reply;
     P data;
-    fillRandomParcel(&data, std::move(provider));
+    fillRandomParcel(&data, std::move(provider), &options);
     (void)binder->transact(code, data, &reply, flag);
 }
 
@@ -73,8 +80,10 @@
     std::vector<uint8_t> instructions = provider.ConsumeBytes<uint8_t>(
             provider.ConsumeIntegralInRange<size_t>(0, maxInstructions));
 
+    RandomParcelOptions options;
+
     P p;
-    fillRandomParcel(&p, std::move(provider));
+    fillRandomParcel(&p, std::move(provider), &options);
 
     // since we are only using a byte to index
     CHECK(reads.size() <= 255) << reads.size();
@@ -103,9 +112,12 @@
     std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(
             provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));
 
+    // same options so that FDs and binders could be shared in both Parcels
+    RandomParcelOptions options;
+
     P p0, p1;
-    fillRandomParcel(&p0, FuzzedDataProvider(bytes.data(), bytes.size()));
-    fillRandomParcel(&p1, std::move(provider));
+    fillRandomParcel(&p0, FuzzedDataProvider(bytes.data(), bytes.size()), &options);
+    fillRandomParcel(&p1, std::move(provider), &options);
 
     FUZZ_LOG() << "backend: " << backend;
     FUZZ_LOG() << "start: " << start << " len: " << len;
diff --git a/libs/binder/tests/parcel_fuzzer/random_fd.cpp b/libs/binder/tests/parcel_fuzzer/random_fd.cpp
index ab0b7e3..3fcf104 100644
--- a/libs/binder/tests/parcel_fuzzer/random_fd.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_fd.cpp
@@ -23,13 +23,44 @@
 
 namespace android {
 
-base::unique_fd getRandomFd(FuzzedDataProvider* provider) {
-    int fd = provider->PickValueInArray<std::function<int()>>({
-            []() { return ashmem_create_region("binder test region", 1024); },
-            []() { return open("/dev/null", O_RDWR); },
+using base::unique_fd;
+
+std::vector<unique_fd> getRandomFds(FuzzedDataProvider* provider) {
+    std::vector<unique_fd> fds = provider->PickValueInArray<
+            std::function<std::vector<unique_fd>()>>({
+            [&]() {
+                std::vector<unique_fd> ret;
+                ret.push_back(unique_fd(
+                        ashmem_create_region("binder test region",
+                                             provider->ConsumeIntegralInRange<size_t>(0, 4096))));
+                return ret;
+            },
+            [&]() {
+                std::vector<unique_fd> ret;
+                ret.push_back(unique_fd(open("/dev/null", O_RDWR)));
+                return ret;
+            },
+            [&]() {
+                int pipefds[2];
+
+                int flags = O_CLOEXEC;
+                if (provider->ConsumeBool()) flags |= O_DIRECT;
+                if (provider->ConsumeBool()) flags |= O_NONBLOCK;
+
+                CHECK_EQ(0, pipe2(pipefds, flags));
+
+                if (provider->ConsumeBool()) std::swap(pipefds[0], pipefds[1]);
+
+                std::vector<unique_fd> ret;
+                ret.push_back(unique_fd(pipefds[0]));
+                ret.push_back(unique_fd(pipefds[1]));
+                return ret;
+            },
     })();
-    CHECK(fd >= 0);
-    return base::unique_fd(fd);
+
+    for (const auto& fd : fds) CHECK(fd.ok()) << fd.get();
+
+    return fds;
 }
 
 } // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 0204f5e..51cb768 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -39,23 +39,24 @@
     CHECK(OK == p->write(data.data(), data.size()));
 }
 
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider,
-                      const RandomParcelOptions& options) {
+void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOptions* options) {
+    CHECK_NE(options, nullptr);
+
     if (provider.ConsumeBool()) {
         auto session = RpcSession::make(RpcTransportCtxFactoryRaw::make());
         CHECK_EQ(OK, session->addNullDebuggingClient());
         p->markForRpc(session);
 
-        if (options.writeHeader) {
-            options.writeHeader(p, provider);
+        if (options->writeHeader) {
+            options->writeHeader(p, provider);
         }
 
         fillRandomParcelData(p, std::move(provider));
         return;
     }
 
-    if (options.writeHeader) {
-        options.writeHeader(p, provider);
+    if (options->writeHeader) {
+        options->writeHeader(p, provider);
     }
 
     while (provider.remaining_bytes() > 0) {
@@ -69,15 +70,21 @@
                 },
                 // write FD
                 [&]() {
-                    if (options.extraFds.size() > 0 && provider.ConsumeBool()) {
-                        const base::unique_fd& fd = options.extraFds.at(
+                    if (options->extraFds.size() > 0 && provider.ConsumeBool()) {
+                        const base::unique_fd& fd = options->extraFds.at(
                                 provider.ConsumeIntegralInRange<size_t>(0,
-                                                                        options.extraFds.size() -
+                                                                        options->extraFds.size() -
                                                                                 1));
                         CHECK(OK == p->writeFileDescriptor(fd.get(), false /*takeOwnership*/));
                     } else {
-                        base::unique_fd fd = getRandomFd(&provider);
-                        CHECK(OK == p->writeFileDescriptor(fd.release(), true /*takeOwnership*/));
+                        std::vector<base::unique_fd> fds = getRandomFds(&provider);
+                        CHECK(OK ==
+                              p->writeFileDescriptor(fds.begin()->release(),
+                                                     true /*takeOwnership*/));
+
+                        options->extraFds.insert(options->extraFds.end(),
+                                                 std::make_move_iterator(fds.begin() + 1),
+                                                 std::make_move_iterator(fds.end()));
                     }
                 },
                 // write binder
@@ -98,10 +105,10 @@
                                 return IInterface::asBinder(defaultServiceManager());
                             },
                             [&]() -> sp<IBinder> {
-                                if (options.extraBinders.size() > 0 && provider.ConsumeBool()) {
-                                    return options.extraBinders.at(
+                                if (options->extraBinders.size() > 0 && provider.ConsumeBool()) {
+                                    return options->extraBinders.at(
                                             provider.ConsumeIntegralInRange<
-                                                    size_t>(0, options.extraBinders.size() - 1));
+                                                    size_t>(0, options->extraBinders.size() - 1));
                                 } else {
                                     return nullptr;
                                 }
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index d169043..706704a 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -131,24 +131,24 @@
     }
 
     gTisTotalMapFd =
-            unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_total_time_in_state_map")};
+            unique_fd{bpf_obj_get(BPF_FS_PATH "map_timeInState_total_time_in_state_map")};
     if (gTisTotalMapFd < 0) return false;
 
-    gTisMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_time_in_state_map")};
+    gTisMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_timeInState_uid_time_in_state_map")};
     if (gTisMapFd < 0) return false;
 
     gConcurrentMapFd =
-            unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_concurrent_times_map")};
+            unique_fd{bpf_obj_get(BPF_FS_PATH "map_timeInState_uid_concurrent_times_map")};
     if (gConcurrentMapFd < 0) return false;
 
     gUidLastUpdateMapFd =
-            unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_last_update_map")};
+            unique_fd{bpf_obj_get(BPF_FS_PATH "map_timeInState_uid_last_update_map")};
     if (gUidLastUpdateMapFd < 0) return false;
 
-    gPidTisMapFd = unique_fd{mapRetrieveRO(BPF_FS_PATH "map_time_in_state_pid_time_in_state_map")};
+    gPidTisMapFd = unique_fd{mapRetrieveRO(BPF_FS_PATH "map_timeInState_pid_time_in_state_map")};
     if (gPidTisMapFd < 0) return false;
 
-    unique_fd trackedPidMapFd(mapRetrieveWO(BPF_FS_PATH "map_time_in_state_pid_tracked_map"));
+    unique_fd trackedPidMapFd(mapRetrieveWO(BPF_FS_PATH "map_timeInState_pid_tracked_map"));
     if (trackedPidMapFd < 0) return false;
 
     gInitialized = true;
@@ -156,7 +156,7 @@
 }
 
 static int retrieveProgramFd(const std::string &eventType, const std::string &eventName) {
-    std::string path = StringPrintf(BPF_FS_PATH "prog_time_in_state_tracepoint_%s_%s",
+    std::string path = StringPrintf(BPF_FS_PATH "prog_timeInState_tracepoint_%s_%s",
                                     eventType.c_str(), eventName.c_str());
     return retrieveProgram(path.c_str());
 }
@@ -200,7 +200,7 @@
     if (!initGlobals()) return false;
     if (gTracking) return true;
 
-    unique_fd cpuPolicyFd(mapRetrieveWO(BPF_FS_PATH "map_time_in_state_cpu_policy_map"));
+    unique_fd cpuPolicyFd(mapRetrieveWO(BPF_FS_PATH "map_timeInState_cpu_policy_map"));
     if (cpuPolicyFd < 0) return false;
 
     for (uint32_t i = 0; i < gPolicyCpus.size(); ++i) {
@@ -209,7 +209,7 @@
         }
     }
 
-    unique_fd freqToIdxFd(mapRetrieveWO(BPF_FS_PATH "map_time_in_state_freq_to_idx_map"));
+    unique_fd freqToIdxFd(mapRetrieveWO(BPF_FS_PATH "map_timeInState_freq_to_idx_map"));
     if (freqToIdxFd < 0) return false;
     freq_idx_key_t key;
     for (uint32_t i = 0; i < gNPolicies; ++i) {
@@ -224,23 +224,23 @@
         }
     }
 
-    unique_fd cpuLastUpdateFd(mapRetrieveWO(BPF_FS_PATH "map_time_in_state_cpu_last_update_map"));
+    unique_fd cpuLastUpdateFd(mapRetrieveWO(BPF_FS_PATH "map_timeInState_cpu_last_update_map"));
     if (cpuLastUpdateFd < 0) return false;
     std::vector<uint64_t> zeros(get_nprocs_conf(), 0);
     uint32_t zero = 0;
     if (writeToMapEntry(cpuLastUpdateFd, &zero, zeros.data(), BPF_ANY)) return false;
 
-    unique_fd nrActiveFd(mapRetrieveWO(BPF_FS_PATH "map_time_in_state_nr_active_map"));
+    unique_fd nrActiveFd(mapRetrieveWO(BPF_FS_PATH "map_timeInState_nr_active_map"));
     if (nrActiveFd < 0) return false;
     if (writeToMapEntry(nrActiveFd, &zero, &zero, BPF_ANY)) return false;
 
-    unique_fd policyNrActiveFd(mapRetrieveWO(BPF_FS_PATH "map_time_in_state_policy_nr_active_map"));
+    unique_fd policyNrActiveFd(mapRetrieveWO(BPF_FS_PATH "map_timeInState_policy_nr_active_map"));
     if (policyNrActiveFd < 0) return false;
     for (uint32_t i = 0; i < gNPolicies; ++i) {
         if (writeToMapEntry(policyNrActiveFd, &i, &zero, BPF_ANY)) return false;
     }
 
-    unique_fd policyFreqIdxFd(mapRetrieveWO(BPF_FS_PATH "map_time_in_state_policy_freq_idx_map"));
+    unique_fd policyFreqIdxFd(mapRetrieveWO(BPF_FS_PATH "map_timeInState_policy_freq_idx_map"));
     if (policyFreqIdxFd < 0) return false;
     for (uint32_t i = 0; i < gNPolicies; ++i) {
         auto freqIdx = getPolicyFreqIdx(i);
@@ -560,10 +560,10 @@
     if (!gInitialized && !initGlobals()) return false;
 
     unique_fd trackedPidHashMapFd(
-            mapRetrieveWO(BPF_FS_PATH "map_time_in_state_pid_tracked_hash_map"));
+            mapRetrieveWO(BPF_FS_PATH "map_timeInState_pid_tracked_hash_map"));
     if (trackedPidHashMapFd < 0) return false;
 
-    unique_fd trackedPidMapFd(mapRetrieveWO(BPF_FS_PATH "map_time_in_state_pid_tracked_map"));
+    unique_fd trackedPidMapFd(mapRetrieveWO(BPF_FS_PATH "map_timeInState_pid_tracked_map"));
     if (trackedPidMapFd < 0) return false;
 
     for (uint32_t index = 0; index < MAX_TRACKED_PIDS; index++) {
@@ -590,7 +590,7 @@
     if (!gInitialized && !initGlobals()) return false;
 
     unique_fd taskAggregationMapFd(
-            mapRetrieveWO(BPF_FS_PATH "map_time_in_state_pid_task_aggregation_map"));
+            mapRetrieveWO(BPF_FS_PATH "map_timeInState_pid_task_aggregation_map"));
     if (taskAggregationMapFd < 0) return false;
 
     return writeToMapEntry(taskAggregationMapFd, &pid, &aggregationKey, BPF_ANY) == 0;
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index 45a6d47..6ccc6ca 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -462,7 +462,7 @@
         ++uid;
     }
     android::base::unique_fd fd{
-        bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_concurrent_times_map")};
+        bpf_obj_get(BPF_FS_PATH "map_timeInState_uid_concurrent_times_map")};
     ASSERT_GE(fd, 0);
     uint32_t nCpus = get_nprocs_conf();
     uint32_t maxBucket = (nCpus - 1) / CPUS_PER_ENTRY;
@@ -504,7 +504,7 @@
     {
         // Add a map entry for our fake UID by copying a real map entry
         android::base::unique_fd fd{
-                bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_time_in_state_map")};
+                bpf_obj_get(BPF_FS_PATH "map_timeInState_uid_time_in_state_map")};
         ASSERT_GE(fd, 0);
         time_key_t k;
         ASSERT_FALSE(getFirstMapKey(fd, &k));
@@ -515,7 +515,7 @@
         ASSERT_FALSE(writeToMapEntry(fd, &k, vals.data(), BPF_NOEXIST));
 
         android::base::unique_fd fd2{
-                bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_concurrent_times_map")};
+                bpf_obj_get(BPF_FS_PATH "map_timeInState_uid_concurrent_times_map")};
         k.uid = copiedUid;
         k.bucket = 0;
         std::vector<concurrent_val_t> cvals(get_nprocs_conf());
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index 988132c..da42a96 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -2,10 +2,10 @@
   global:
     AHardwareBuffer_acquire;
     AHardwareBuffer_allocate;
-    AHardwareBuffer_createFromHandle; # llndk # apex
+    AHardwareBuffer_createFromHandle; # llndk # systemapi
     AHardwareBuffer_describe;
     AHardwareBuffer_getId; # introduced=31
-    AHardwareBuffer_getNativeHandle; # llndk # apex
+    AHardwareBuffer_getNativeHandle; # llndk # systemapi
     AHardwareBuffer_isSupported; # introduced=29
     AHardwareBuffer_lock;
     AHardwareBuffer_lockAndGetInfo; # introduced=29
@@ -23,18 +23,18 @@
     ANativeWindow_getBuffersDataSpace; # introduced=28
     ANativeWindow_getFormat;
     ANativeWindow_getHeight;
-    ANativeWindow_getLastDequeueDuration; # apex # introduced=30
-    ANativeWindow_getLastDequeueStartTime; # apex # introduced=30
-    ANativeWindow_getLastQueueDuration; # apex # introduced=30
+    ANativeWindow_getLastDequeueDuration; # systemapi # introduced=30
+    ANativeWindow_getLastDequeueStartTime; # systemapi # introduced=30
+    ANativeWindow_getLastQueueDuration; # systemapi # introduced=30
     ANativeWindow_getWidth;
     ANativeWindow_lock;
     ANativeWindow_query; # llndk
     ANativeWindow_queryf; # llndk
     ANativeWindow_queueBuffer; # llndk
-    ANativeWindow_setCancelBufferInterceptor; # apex # introduced=30
-    ANativeWindow_setDequeueBufferInterceptor; # apex # introduced=30
-    ANativeWindow_setPerformInterceptor; # apex # introduced=30
-    ANativeWindow_setQueueBufferInterceptor; # apex # introduced=30
+    ANativeWindow_setCancelBufferInterceptor; # systemapi # introduced=30
+    ANativeWindow_setDequeueBufferInterceptor; # systemapi # introduced=30
+    ANativeWindow_setPerformInterceptor; # systemapi # introduced=30
+    ANativeWindow_setQueueBufferInterceptor; # systemapi # introduced=30
     ANativeWindow_release;
     ANativeWindow_setAutoPrerotation; # llndk
     ANativeWindow_setAutoRefresh; # llndk
@@ -45,7 +45,7 @@
     ANativeWindow_setBuffersGeometry;
     ANativeWindow_setBuffersTimestamp; # llndk
     ANativeWindow_setBuffersTransform;
-    ANativeWindow_setDequeueTimeout; # apex # introduced=30
+    ANativeWindow_setDequeueTimeout; # systemapi # introduced=30
     ANativeWindow_setFrameRate; # introduced=30
     ANativeWindow_setFrameRateWithChangeStrategy; # introduced=31
     ANativeWindow_setSharedBufferMode; # llndk
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index b9b6a19..0411b31 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -98,7 +98,7 @@
     init_rc: ["gpuservice.rc"],
     required: [
         "bpfloader",
-        "gpu_mem.o",
+        "gpuMem.o",
     ],
     srcs: [":gpuservice_binary_sources"],
     shared_libs: [
diff --git a/services/gpuservice/CleanSpec.mk b/services/gpuservice/CleanSpec.mk
index 482fc6d..c51f6aa 100644
--- a/services/gpuservice/CleanSpec.mk
+++ b/services/gpuservice/CleanSpec.mk
@@ -44,9 +44,9 @@
 #$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
 #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
 
-# Remove gpu_mem.o
+# Remove gpuMem.o
 $(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/frameworks/native/services/gpuservice/bpf)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/FAKE/gpu_mem.o_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/ETC/gpu_mem.o_gpu_mem.o_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/bpf/gpu_mem.o)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/fake_packages/gpu_mem.o-timestamp)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/FAKE/gpuMem.o_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/ETC/gpuMem.o_gpuMem.o_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/bpf/gpuMem.o)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/fake_packages/gpuMem.o-timestamp)
diff --git a/services/gpuservice/bpfprogs/Android.bp b/services/gpuservice/bpfprogs/Android.bp
index 076affd..680b291 100644
--- a/services/gpuservice/bpfprogs/Android.bp
+++ b/services/gpuservice/bpfprogs/Android.bp
@@ -22,8 +22,8 @@
 }
 
 bpf {
-    name: "gpu_mem.o",
-    srcs: ["gpu_mem.c"],
+    name: "gpuMem.o",
+    srcs: ["gpuMem.c"],
     btf: true,
     cflags: [
         "-Wall",
diff --git a/services/gpuservice/bpfprogs/gpu_mem.c b/services/gpuservice/bpfprogs/gpuMem.c
similarity index 100%
rename from services/gpuservice/bpfprogs/gpu_mem.c
rename to services/gpuservice/bpfprogs/gpuMem.c
diff --git a/services/gpuservice/gpumem/include/gpumem/GpuMem.h b/services/gpuservice/gpumem/include/gpumem/GpuMem.h
index de691e2..7588b54 100644
--- a/services/gpuservice/gpumem/include/gpumem/GpuMem.h
+++ b/services/gpuservice/gpumem/include/gpumem/GpuMem.h
@@ -57,9 +57,9 @@
     static constexpr char kGpuMemTotalTracepoint[] = "gpu_mem_total";
     // pinned gpu memory total bpf c program path in bpf sysfs
     static constexpr char kGpuMemTotalProgPath[] =
-            "/sys/fs/bpf/prog_gpu_mem_tracepoint_gpu_mem_gpu_mem_total";
+            "/sys/fs/bpf/prog_gpuMem_tracepoint_gpu_mem_gpu_mem_total";
     // pinned gpu memory total bpf map path in bpf sysfs
-    static constexpr char kGpuMemTotalMapPath[] = "/sys/fs/bpf/map_gpu_mem_gpu_mem_total_map";
+    static constexpr char kGpuMemTotalMapPath[] = "/sys/fs/bpf/map_gpuMem_gpu_mem_total_map";
     // 30 seconds timeout for trying to attach bpf program to tracepoint
     static constexpr int kGpuWaitTimeout = 30;
 };
diff --git a/services/gpuservice/tests/unittests/GpuMemTest.cpp b/services/gpuservice/tests/unittests/GpuMemTest.cpp
index 36ae179..8dabe4f 100644
--- a/services/gpuservice/tests/unittests/GpuMemTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuMemTest.cpp
@@ -90,8 +90,8 @@
     EXPECT_EQ(mTestableGpuMem.getGpuMemTraceGroup(), "gpu_mem");
     EXPECT_EQ(mTestableGpuMem.getGpuMemTotalTracepoint(), "gpu_mem_total");
     EXPECT_EQ(mTestableGpuMem.getGpuMemTotalProgPath(),
-              "/sys/fs/bpf/prog_gpu_mem_tracepoint_gpu_mem_gpu_mem_total");
-    EXPECT_EQ(mTestableGpuMem.getGpuMemTotalMapPath(), "/sys/fs/bpf/map_gpu_mem_gpu_mem_total_map");
+              "/sys/fs/bpf/prog_gpuMem_tracepoint_gpu_mem_gpu_mem_total");
+    EXPECT_EQ(mTestableGpuMem.getGpuMemTotalMapPath(), "/sys/fs/bpf/map_gpuMem_gpu_mem_total_map");
 }
 
 TEST_F(GpuMemTest, bpfInitializationFailed) {
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 2ac41b1..231f825 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -64,7 +64,11 @@
 CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext)
       : InputMapper(deviceContext) {}
 
-CursorInputMapper::~CursorInputMapper() {}
+CursorInputMapper::~CursorInputMapper() {
+    if (mPointerController != nullptr) {
+        mPointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
+    }
+}
 
 uint32_t CursorInputMapper::getSources() {
     return mSource;
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index e60625b..0afbe11 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -755,7 +755,11 @@
     // We must support R8G8B8A8
     std::vector<VkSurfaceFormatKHR> all_formats = {
         {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
-        {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
+        {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+        // Also allow to use PASS_THROUGH + HAL_DATASPACE_ARBITRARY
+        {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_PASS_THROUGH_EXT},
+        {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_PASS_THROUGH_EXT},
+    };
 
     if (colorspace_ext) {
         all_formats.emplace_back(VkSurfaceFormatKHR{
@@ -777,12 +781,16 @@
     if (AHardwareBuffer_isSupported(&desc)) {
         all_formats.emplace_back(VkSurfaceFormatKHR{
             VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
+        all_formats.emplace_back(VkSurfaceFormatKHR{
+            VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_PASS_THROUGH_EXT});
     }
 
     desc.format = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
     if (AHardwareBuffer_isSupported(&desc)) {
         all_formats.emplace_back(VkSurfaceFormatKHR{
             VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
+        all_formats.emplace_back(VkSurfaceFormatKHR{
+            VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_PASS_THROUGH_EXT});
         if (wide_color_support) {
             all_formats.emplace_back(
                 VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
@@ -798,6 +806,9 @@
         all_formats.emplace_back(
             VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
                                VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
+        all_formats.emplace_back(
+            VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
+                               VK_COLOR_SPACE_PASS_THROUGH_EXT});
         if (wide_color_support) {
             all_formats.emplace_back(
                 VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,