Merge "Set linker namespaces to null if VNDK namespace is not available" into main
diff --git a/aidl/gui/android/view/Surface.aidl b/aidl/gui/android/view/Surface.aidl
index bb3faaf..6686717 100644
--- a/aidl/gui/android/view/Surface.aidl
+++ b/aidl/gui/android/view/Surface.aidl
@@ -17,4 +17,4 @@
 
 package android.view;
 
-@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable Surface cpp_header "gui/view/Surface.h" ndk_header "android/native_window_aidl.h";
+@JavaOnlyStableParcelable @NdkOnlyStableParcelable @RustOnlyStableParcelable parcelable Surface cpp_header "gui/view/Surface.h" ndk_header "android/native_window_aidl.h" rust_type "nativewindow::Surface";
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 5719a09..cd4926a 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -313,12 +313,6 @@
 static const char* k_traceBufferSizePath =
     "buffer_size_kb";
 
-#if 0
-// TODO: Re-enable after stabilization
-static const char* k_traceCmdlineSizePath =
-    "saved_cmdlines_size";
-#endif
-
 static const char* k_tracingOverwriteEnablePath =
     "options/overwrite";
 
@@ -545,18 +539,6 @@
     return writeStr(k_traceBufferSizePath, str);
 }
 
-#if 0
-// TODO: Re-enable after stabilization
-// Set the default size of cmdline hashtable
-static bool setCmdlineSize()
-{
-    if (fileExists(k_traceCmdlineSizePath)) {
-        return writeStr(k_traceCmdlineSizePath, "8192");
-    }
-    return true;
-}
-#endif
-
 // Set the clock to the best available option while tracing. Use 'boot' if it's
 // available; otherwise, use 'mono'. If neither are available use 'global'.
 // Any write to the trace_clock sysfs file will reset the buffer, so only
@@ -870,8 +852,6 @@
     ok &= setCategoriesEnableFromFile(g_categoriesFile);
     ok &= setTraceOverwriteEnable(g_traceOverwrite);
     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
-    // TODO: Re-enable after stabilization
-    //ok &= setCmdlineSize();
     ok &= setClock();
     ok &= setPrintTgidEnableIfPresent(true);
     ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 3e6d2e0..9b357e7 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -13,6 +13,8 @@
 # Access control to these files is now entirely in selinux policy.
     chmod 0666 /sys/kernel/debug/tracing/trace_clock
     chmod 0666 /sys/kernel/tracing/trace_clock
+    chmod 0666 /sys/kernel/debug/tracing/buffer_percent
+    chmod 0666 /sys/kernel/tracing/buffer_percent
     chmod 0666 /sys/kernel/debug/tracing/buffer_size_kb
     chmod 0666 /sys/kernel/tracing/buffer_size_kb
     chmod 0666 /sys/kernel/debug/tracing/options/overwrite
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 71a8740..9399c73 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -4029,24 +4029,37 @@
         return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Received a null auth token");
     }
 
-    // Authenticate to check the targeting file is the same inode as the authFd.
+    // Authenticate to check the targeting file is the same inode as the authFd. With O_PATH, we
+    // prevent a malicious client from blocking installd by providing a path to FIFO. After the
+    // authentication, the actual open is safe.
     sp<IBinder> authTokenBinder = IInterface::asBinder(authToken)->localBinder();
     if (authTokenBinder == nullptr) {
         return exception(binder::Status::EX_SECURITY, "Received a non-local auth token");
     }
-    auto authTokenInstance = sp<FsveritySetupAuthToken>::cast(authTokenBinder);
-    unique_fd rfd(open(filePath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
-    struct stat stFromPath;
-    if (fstat(rfd.get(), &stFromPath) < 0) {
-        *_aidl_return = errno;
+    unique_fd pathFd(open(filePath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_PATH));
+    // Returns a constant errno to avoid one app probing file existence of the others, before the
+    // authentication is done.
+    const int kFixedErrno = EPERM;
+    if (pathFd.get() < 0) {
+        PLOG(DEBUG) << "Failed to open the path";
+        *_aidl_return = kFixedErrno;
         return ok();
     }
+    std::string procFdPath(StringPrintf("/proc/self/fd/%d", pathFd.get()));
+    struct stat stFromPath;
+    if (stat(procFdPath.c_str(), &stFromPath) < 0) {
+        PLOG(DEBUG) << "Failed to stat proc fd " << pathFd.get() << " -> " << filePath;
+        *_aidl_return = kFixedErrno;
+        return ok();
+    }
+    auto authTokenInstance = sp<FsveritySetupAuthToken>::cast(authTokenBinder);
     if (!authTokenInstance->isSameStat(stFromPath)) {
         LOG(DEBUG) << "FD authentication failed";
-        *_aidl_return = EPERM;
+        *_aidl_return = kFixedErrno;
         return ok();
     }
 
+    unique_fd rfd(open(procFdPath.c_str(), O_RDONLY | O_CLOEXEC));
     fsverity_enable_arg arg = {};
     arg.version = 1;
     arg.hash_algorithm = FS_VERITY_HASH_ALG_SHA256;
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index f2b578a..023491f 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -194,6 +194,12 @@
     });
 }
 
+static void unlink_path(const std::string& path) {
+    if (unlink(path.c_str()) < 0) {
+        PLOG(DEBUG) << "Failed to unlink " + path;
+    }
+}
+
 class ServiceTest : public testing::Test {
 protected:
     InstalldNativeService* service;
@@ -555,7 +561,7 @@
 TEST_F(FsverityTest, enableFsverity) {
     const std::string path = kTestPath + "/foo";
     create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
-    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+    UniqueFile raii(/*fd=*/-1, path, &unlink_path);
 
     // Expect to fs-verity setup to succeed
     sp<IFsveritySetupAuthToken> authToken;
@@ -573,7 +579,7 @@
 TEST_F(FsverityTest, enableFsverity_nullAuthToken) {
     const std::string path = kTestPath + "/foo";
     create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
-    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+    UniqueFile raii(/*fd=*/-1, path, &unlink_path);
 
     // Verity null auth token fails
     sp<IFsveritySetupAuthToken> authToken;
@@ -586,7 +592,7 @@
 TEST_F(FsverityTest, enableFsverity_differentFile) {
     const std::string path = kTestPath + "/foo";
     create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
-    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+    UniqueFile raii(/*fd=*/-1, path, &unlink_path);
 
     // Expect to fs-verity setup to succeed
     sp<IFsveritySetupAuthToken> authToken;
@@ -597,17 +603,36 @@
     // Verity auth token does not work for a different file
     const std::string anotherPath = kTestPath + "/bar";
     ASSERT_TRUE(android::base::WriteStringToFile("content", anotherPath));
-    UniqueFile raii2(/*fd=*/-1, anotherPath, [](const std::string& path) { unlink(path.c_str()); });
+    UniqueFile raii2(/*fd=*/-1, anotherPath, &unlink_path);
     int32_t errno_local;
     status = service->enableFsverity(authToken, anotherPath, "fake.package.name", &errno_local);
     EXPECT_TRUE(status.isOk());
     EXPECT_NE(errno_local, 0);
 }
 
+TEST_F(FsverityTest, enableFsverity_errnoBeforeAuthenticated) {
+    const std::string path = kTestPath + "/foo";
+    create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
+    UniqueFile raii(/*fd=*/-1, path, &unlink_path);
+
+    // Expect to fs-verity setup to succeed
+    sp<IFsveritySetupAuthToken> authToken;
+    binder::Status status = createFsveritySetupAuthToken(path, O_RDWR, &authToken);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_TRUE(authToken != nullptr);
+
+    // Verity errno before the fd authentication is constant (EPERM)
+    int32_t errno_local;
+    status = service->enableFsverity(authToken, path + "-non-exist", "fake.package.name",
+                                     &errno_local);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_EQ(errno_local, EPERM);
+}
+
 TEST_F(FsverityTest, createFsveritySetupAuthToken_ReadonlyFdDoesNotAuthenticate) {
     const std::string path = kTestPath + "/foo";
     create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
-    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+    UniqueFile raii(/*fd=*/-1, path, &unlink_path);
 
     // Expect the fs-verity setup to fail
     sp<IFsveritySetupAuthToken> authToken;
@@ -619,7 +644,7 @@
     const std::string path = kTestPath + "/foo";
     // Simulate world-writable file owned by another app
     create_with_content(path, kTestAppUid + 1, kTestAppUid + 1, 0666, "content");
-    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+    UniqueFile raii(/*fd=*/-1, path, &unlink_path);
 
     // Expect the fs-verity setup to fail
     sp<IFsveritySetupAuthToken> authToken;
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 6115da7..5cdcb23 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -232,6 +232,11 @@
         return static_cast<HelpCommand*>(help)->usageOfCommand(mCommand);
     }
 
+    // After Lshal::main() finishes, caller may call _exit(), causing debug
+    // information to prematurely ends. Hence flush().
+    err().flush();
+    out().flush();
+
     return status;
 }
 
diff --git a/cmds/lshal/NullableOStream.h b/cmds/lshal/NullableOStream.h
index 7cffcf8..1576486 100644
--- a/cmds/lshal/NullableOStream.h
+++ b/cmds/lshal/NullableOStream.h
@@ -59,6 +59,11 @@
     operator bool() const { // NOLINT(google-explicit-constructor)
         return mOs != nullptr;
     }
+    void flush() {
+        if (mOs) {
+            mOs->flush();
+        }
+    }
 private:
     template<typename>
     friend class NullableOStream;
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index e00c2a2..3897197 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -95,6 +95,16 @@
     static_libs: ["libgmock"],
 }
 
+cc_test_host {
+    name: "servicemanager_unittest",
+    test_suites: ["general-tests"],
+    defaults: ["servicemanager_defaults"],
+    srcs: [
+        "ServiceManagerUnittest.cpp",
+    ],
+    static_libs: ["libgmock"],
+}
+
 cc_fuzz {
     name: "servicemanager_fuzzer",
     defaults: [
diff --git a/cmds/servicemanager/NameUtil.h b/cmds/servicemanager/NameUtil.h
new file mode 100644
index 0000000..b080939
--- /dev/null
+++ b/cmds/servicemanager/NameUtil.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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 <string>
+#include <string_view>
+
+#include <android-base/strings.h>
+
+namespace android {
+
+#ifndef VENDORSERVICEMANAGER
+
+struct NativeName {
+    std::string package;
+    std::string instance;
+
+    // Parse {package}/{instance}
+    static bool fill(std::string_view name, NativeName* nname) {
+        size_t slash = name.find('/');
+        if (slash == std::string_view::npos) {
+            return false;
+        }
+        // no extra slashes
+        if (name.find('/', slash + 1) != std::string_view::npos) {
+            return false;
+        }
+        // every part should be non-empty
+        if (slash == 0 || slash + 1 == name.size()) {
+            return false;
+        }
+        // no dots in package
+        if (name.rfind('.', slash) != std::string_view::npos) {
+            return false;
+        }
+        nname->package = name.substr(0, slash);
+        nname->instance = name.substr(slash + 1);
+        return true;
+    }
+};
+
+#endif
+
+} // namespace android
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 77989d1..bf85e61 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -35,6 +35,8 @@
 #include <vintf/constants.h>
 #endif  // !VENDORSERVICEMANAGER
 
+#include "NameUtil.h"
+
 using ::android::binder::Status;
 using ::android::internal::Stability;
 
@@ -84,6 +86,10 @@
     return false;
 }
 
+static std::string getNativeInstanceName(const vintf::ManifestInstance& instance) {
+    return instance.package() + "/" + instance.instance();
+}
+
 struct AidlName {
     std::string package;
     std::string iface;
@@ -105,7 +111,26 @@
     }
 };
 
+static std::string getAidlInstanceName(const vintf::ManifestInstance& instance) {
+    return instance.package() + "." + instance.interface() + "/" + instance.instance();
+}
+
 static bool isVintfDeclared(const std::string& name) {
+    NativeName nname;
+    if (NativeName::fill(name, &nname)) {
+        bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
+            if (mwd.manifest->hasNativeInstance(nname.package, nname.instance)) {
+                ALOGI("Found %s in %s VINTF manifest.", name.c_str(), mwd.description);
+                return true; // break
+            }
+            return false; // continue
+        });
+        if (!found) {
+            ALOGI("Could not find %s in the VINTF manifest.", name.c_str());
+        }
+        return found;
+    }
+
     AidlName aname;
     if (!AidlName::fill(name, &aname)) return false;
 
@@ -144,13 +169,31 @@
 }
 
 static std::optional<std::string> getVintfUpdatableApex(const std::string& name) {
+    NativeName nname;
+    if (NativeName::fill(name, &nname)) {
+        std::optional<std::string> updatableViaApex;
+
+        forEachManifest([&](const ManifestWithDescription& mwd) {
+            bool cont = mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+                if (manifestInstance.format() != vintf::HalFormat::NATIVE) return true;
+                if (manifestInstance.package() != nname.package) return true;
+                if (manifestInstance.instance() != nname.instance) return true;
+                updatableViaApex = manifestInstance.updatableViaApex();
+                return false; // break (libvintf uses opposite convention)
+            });
+            return !cont;
+        });
+
+        return updatableViaApex;
+    }
+
     AidlName aname;
     if (!AidlName::fill(name, &aname)) return std::nullopt;
 
     std::optional<std::string> updatableViaApex;
 
     forEachManifest([&](const ManifestWithDescription& mwd) {
-        mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+        bool cont = mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
             if (manifestInstance.format() != vintf::HalFormat::AIDL) return true;
             if (manifestInstance.package() != aname.package) return true;
             if (manifestInstance.interface() != aname.iface) return true;
@@ -158,31 +201,31 @@
             updatableViaApex = manifestInstance.updatableViaApex();
             return false; // break (libvintf uses opposite convention)
         });
-        if (updatableViaApex.has_value()) return true; // break (found match)
-        return false; // continue
+        return !cont;
     });
 
     return updatableViaApex;
 }
 
-static std::vector<std::string> getVintfUpdatableInstances(const std::string& apexName) {
-    std::vector<std::string> instances;
+static std::vector<std::string> getVintfUpdatableNames(const std::string& apexName) {
+    std::vector<std::string> names;
 
     forEachManifest([&](const ManifestWithDescription& mwd) {
         mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
-            if (manifestInstance.format() == vintf::HalFormat::AIDL &&
-                manifestInstance.updatableViaApex().has_value() &&
+            if (manifestInstance.updatableViaApex().has_value() &&
                 manifestInstance.updatableViaApex().value() == apexName) {
-                std::string aname = manifestInstance.package() + "." +
-                        manifestInstance.interface() + "/" + manifestInstance.instance();
-                instances.push_back(aname);
+                if (manifestInstance.format() == vintf::HalFormat::NATIVE) {
+                    names.push_back(getNativeInstanceName(manifestInstance));
+                } else if (manifestInstance.format() == vintf::HalFormat::AIDL) {
+                    names.push_back(getAidlInstanceName(manifestInstance));
+                }
             }
             return true; // continue (libvintf uses opposite convention)
         });
         return false; // continue
     });
 
-    return instances;
+    return names;
 }
 
 static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
@@ -217,6 +260,18 @@
 static std::vector<std::string> getVintfInstances(const std::string& interface) {
     size_t lastDot = interface.rfind('.');
     if (lastDot == std::string::npos) {
+        // This might be a package for native instance.
+        std::vector<std::string> ret;
+        (void)forEachManifest([&](const ManifestWithDescription& mwd) {
+            auto instances = mwd.manifest->getNativeInstances(interface);
+            ret.insert(ret.end(), instances.begin(), instances.end());
+            return false; // continue
+        });
+        // If found, return it without error log.
+        if (!ret.empty()) {
+            return ret;
+        }
+
         ALOGE("VINTF interfaces require names in Java package format (e.g. some.package.foo.IFoo) "
               "but got: %s",
               interface.c_str());
@@ -594,20 +649,20 @@
                                          std::vector<std::string>* outReturn) {
     auto ctx = mAccess->getCallingContext();
 
-    std::vector<std::string> apexUpdatableInstances;
+    std::vector<std::string> apexUpdatableNames;
 #ifndef VENDORSERVICEMANAGER
-    apexUpdatableInstances = getVintfUpdatableInstances(apexName);
+    apexUpdatableNames = getVintfUpdatableNames(apexName);
 #endif
 
     outReturn->clear();
 
-    for (const std::string& instance : apexUpdatableInstances) {
-        if (mAccess->canFind(ctx, instance)) {
-            outReturn->push_back(instance);
+    for (const std::string& name : apexUpdatableNames) {
+        if (mAccess->canFind(ctx, name)) {
+            outReturn->push_back(name);
         }
     }
 
-    if (outReturn->size() == 0 && apexUpdatableInstances.size() != 0) {
+    if (outReturn->size() == 0 && apexUpdatableNames.size() != 0) {
         return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
     }
 
diff --git a/cmds/servicemanager/ServiceManagerUnittest.cpp b/cmds/servicemanager/ServiceManagerUnittest.cpp
new file mode 100644
index 0000000..39d20b0
--- /dev/null
+++ b/cmds/servicemanager/ServiceManagerUnittest.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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 <gtest/gtest.h>
+
+#include "NameUtil.h"
+
+namespace android {
+
+TEST(ServiceManager, NativeName) {
+    NativeName nname;
+    EXPECT_TRUE(NativeName::fill("mapper/default", &nname));
+    EXPECT_EQ("mapper", nname.package);
+    EXPECT_EQ("default", nname.instance);
+}
+
+TEST(ServiceManager, NativeName_Malformed) {
+    NativeName nname;
+    EXPECT_FALSE(NativeName::fill("mapper", &nname));
+    EXPECT_FALSE(NativeName::fill("mapper/", &nname));
+    EXPECT_FALSE(NativeName::fill("/default", &nname));
+    EXPECT_FALSE(NativeName::fill("mapper/default/0", &nname));
+    EXPECT_FALSE(NativeName::fill("aidl.like.IType/default", &nname));
+}
+
+} // namespace android
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index ae56cb0..07908ba 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -40,15 +40,12 @@
 public:
     static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
         sp<BinderCallback> cb = sp<BinderCallback>::make();
+        cb->mLooper = looper;
 
-        int binder_fd = -1;
-        IPCThreadState::self()->setupPolling(&binder_fd);
-        LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);
+        IPCThreadState::self()->setupPolling(&cb->mBinderFd);
+        LOG_ALWAYS_FATAL_IF(cb->mBinderFd < 0, "Failed to setupPolling: %d", cb->mBinderFd);
 
-        int ret = looper->addFd(binder_fd,
-                                Looper::POLL_CALLBACK,
-                                Looper::EVENT_INPUT,
-                                cb,
+        int ret = looper->addFd(cb->mBinderFd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb,
                                 nullptr /*data*/);
         LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");
 
@@ -59,13 +56,26 @@
         IPCThreadState::self()->handlePolledCommands();
         return 1;  // Continue receiving callbacks.
     }
+
+    void repoll() {
+        if (!mLooper->repoll(mBinderFd)) {
+            ALOGE("Failed to repoll binder FD.");
+        }
+    }
+
+private:
+    sp<Looper> mLooper;
+    int mBinderFd = -1;
 };
 
 // LooperCallback for IClientCallback
 class ClientCallbackCallback : public LooperCallback {
 public:
-    static sp<ClientCallbackCallback> setupTo(const sp<Looper>& looper, const sp<ServiceManager>& manager) {
+    static sp<ClientCallbackCallback> setupTo(const sp<Looper>& looper,
+                                              const sp<ServiceManager>& manager,
+                                              sp<BinderCallback> binderCallback) {
         sp<ClientCallbackCallback> cb = sp<ClientCallbackCallback>::make(manager);
+        cb->mBinderCallback = binderCallback;
 
         int fdTimer = timerfd_create(CLOCK_MONOTONIC, 0 /*flags*/);
         LOG_ALWAYS_FATAL_IF(fdTimer < 0, "Failed to timerfd_create: fd: %d err: %d", fdTimer, errno);
@@ -102,12 +112,15 @@
         }
 
         mManager->handleClientCallbacks();
+        mBinderCallback->repoll(); // b/316829336
+
         return 1;  // Continue receiving callbacks.
     }
 private:
     friend sp<ClientCallbackCallback>;
     ClientCallbackCallback(const sp<ServiceManager>& manager) : mManager(manager) {}
     sp<ServiceManager> mManager;
+    sp<BinderCallback> mBinderCallback;
 };
 
 int main(int argc, char** argv) {
@@ -139,8 +152,8 @@
 
     sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
 
-    BinderCallback::setupTo(looper);
-    ClientCallbackCallback::setupTo(looper, manager);
+    sp<BinderCallback> binderCallback = BinderCallback::setupTo(looper);
+    ClientCallbackCallback::setupTo(looper, manager, binderCallback);
 
 #ifndef VENDORSERVICEMANAGER
     if (!SetProperty("servicemanager.ready", "true")) {
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index 97e500d..b575053 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -361,6 +361,24 @@
     EXPECT_EQ(std::vector<std::string>{}, names);
 }
 
+TEST(Vintf, IsDeclared_native) {
+    if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
+
+    auto sm = getPermissiveServiceManager();
+    bool declared = false;
+    EXPECT_TRUE(sm->isDeclared("mapper/minigbm", &declared).isOk());
+    EXPECT_TRUE(declared);
+}
+
+TEST(Vintf, GetDeclaredInstances_native) {
+    if (!isCuttlefishPhone()) GTEST_SKIP() << "Skipping non-Cuttlefish-phone devices";
+
+    auto sm = getPermissiveServiceManager();
+    std::vector<std::string> instances;
+    EXPECT_TRUE(sm->getDeclaredInstances("mapper", &instances).isOk());
+    EXPECT_EQ(std::vector<std::string>{"minigbm"}, instances);
+}
+
 class CallbackHistorian : public BnServiceCallback {
     Status onRegistration(const std::string& name, const sp<IBinder>& binder) override {
         registrations.push_back(name);
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index ae0fb01..84ff9d7 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -320,6 +320,24 @@
                 "ServiceManagerHost.cpp",
             ],
         },
+        android: {
+            shared_libs: [
+                "libapexsupport",
+                "libvndksupport",
+            ],
+        },
+        recovery: {
+            exclude_shared_libs: [
+                "libapexsupport",
+                "libvndksupport",
+            ],
+        },
+        native_bridge: {
+            exclude_shared_libs: [
+                "libapexsupport",
+                "libvndksupport",
+            ],
+        },
     },
     cflags: [
         "-DBINDER_WITH_KERNEL_IPC",
@@ -646,9 +664,7 @@
     // Do not expand the visibility.
     visibility: [
         ":__subpackages__",
-        "//packages/modules/Virtualization/javalib/jni",
-        "//packages/modules/Virtualization/vm_payload",
-        "//packages/modules/Virtualization/demo_native",
+        "//packages/modules/Virtualization:__subpackages__",
         "//device/google/cuttlefish/shared/minidroid:__subpackages__",
         "//system/software_defined_vehicle:__subpackages__",
     ],
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index b92e504..ef96f80 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -922,28 +922,10 @@
     flushIfNeeded();
 }
 
-status_t IPCThreadState::attemptIncStrongHandle(int32_t handle)
-{
-#if HAS_BC_ATTEMPT_ACQUIRE
-    LOG_REMOTEREFS("IPCThreadState::attemptIncStrongHandle(%d)\n", handle);
-    mOut.writeInt32(BC_ATTEMPT_ACQUIRE);
-    mOut.writeInt32(0); // xxx was thread priority
-    mOut.writeInt32(handle);
-    status_t result = UNKNOWN_ERROR;
-
-    waitForResponse(NULL, &result);
-
-#if LOG_REFCOUNTS
-    ALOGV("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n",
-        handle, result == NO_ERROR ? "SUCCESS" : "FAILURE");
-#endif
-
-    return result;
-#else
+status_t IPCThreadState::attemptIncStrongHandle(int32_t handle) {
     (void)handle;
     ALOGE("%s(%d): Not supported\n", __func__, handle);
     return INVALID_OPERATION;
-#endif
 }
 
 void IPCThreadState::expungeHandle(int32_t handle, IBinder* binder)
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index fe566fc..39573ec 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -40,6 +40,11 @@
 #include "ServiceManagerHost.h"
 #endif
 
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) && !defined(__ANDROID_NATIVE_BRIDGE__)
+#include <android/apexsupport.h>
+#include <vndksupport/linker.h>
+#endif
+
 #include "Static.h"
 
 namespace android {
@@ -259,6 +264,27 @@
     }
 }
 
+void* openDeclaredPassthroughHal(const String16& interface, const String16& instance, int flag) {
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) && !defined(__ANDROID_NATIVE_BRIDGE__)
+    sp<IServiceManager> sm = defaultServiceManager();
+    String16 name = interface + String16("/") + instance;
+    if (!sm->isDeclared(name)) {
+        return nullptr;
+    }
+    String16 libraryName = interface + String16(".") + instance + String16(".so");
+    if (auto updatableViaApex = sm->updatableViaApex(name); updatableViaApex.has_value()) {
+        return AApexSupport_loadLibrary(String8(libraryName).c_str(),
+                                        String8(*updatableViaApex).c_str(), flag);
+    }
+    return android_load_sphal_library(String8(libraryName).c_str(), flag);
+#else
+    (void)interface;
+    (void)instance;
+    (void)flag;
+    return nullptr;
+#endif
+}
+
 #endif //__ANDROID_VNDK__
 
 // ----------------------------------------------------------------------
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 7de94e3..fb2781b 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -492,6 +492,7 @@
     if (read(fd, &on, sizeof(on)) == -1) {
         ALOGE("%s: error reading to %s: %s", __func__,
                  names[static_cast<int>(feature)], strerror(errno));
+        close(fd);
         return false;
     }
     close(fd);
diff --git a/libs/binder/RecordedTransaction.cpp b/libs/binder/RecordedTransaction.cpp
index 525ba2e..de2a69f 100644
--- a/libs/binder/RecordedTransaction.cpp
+++ b/libs/binder/RecordedTransaction.cpp
@@ -114,8 +114,8 @@
 
 RecordedTransaction::RecordedTransaction(RecordedTransaction&& t) noexcept {
     mData = t.mData;
-    mSent.setData(t.getDataParcel().data(), t.getDataParcel().dataSize());
-    mReply.setData(t.getReplyParcel().data(), t.getReplyParcel().dataSize());
+    mSentDataOnly.setData(t.getDataParcel().data(), t.getDataParcel().dataSize());
+    mReplyDataOnly.setData(t.getReplyParcel().data(), t.getReplyParcel().dataSize());
 }
 
 std::optional<RecordedTransaction> RecordedTransaction::fromDetails(
@@ -136,12 +136,21 @@
         return std::nullopt;
     }
 
-    if (t.mSent.setData(dataParcel.data(), dataParcel.dataBufferSize()) != android::NO_ERROR) {
+    if (const auto* kernelFields = dataParcel.maybeKernelFields()) {
+        for (size_t i = 0; i < kernelFields->mObjectsSize; i++) {
+            uint64_t offset = kernelFields->mObjects[i];
+            t.mData.mSentObjectData.push_back(offset);
+        }
+    }
+
+    if (t.mSentDataOnly.setData(dataParcel.data(), dataParcel.dataBufferSize()) !=
+        android::NO_ERROR) {
         ALOGE("Failed to set sent parcel data.");
         return std::nullopt;
     }
 
-    if (t.mReply.setData(replyParcel.data(), replyParcel.dataBufferSize()) != android::NO_ERROR) {
+    if (t.mReplyDataOnly.setData(replyParcel.data(), replyParcel.dataBufferSize()) !=
+        android::NO_ERROR) {
         ALOGE("Failed to set reply parcel data.");
         return std::nullopt;
     }
@@ -154,6 +163,7 @@
     DATA_PARCEL_CHUNK = 2,
     REPLY_PARCEL_CHUNK = 3,
     INTERFACE_NAME_CHUNK = 4,
+    DATA_PARCEL_OBJECT_CHUNK = 5,
     END_CHUNK = 0x00ffffff,
 };
 
@@ -265,21 +275,30 @@
                 break;
             }
             case DATA_PARCEL_CHUNK: {
-                if (t.mSent.setData(reinterpret_cast<const unsigned char*>(payloadMap),
-                                    chunk.dataSize) != android::NO_ERROR) {
+                if (t.mSentDataOnly.setData(reinterpret_cast<const unsigned char*>(payloadMap),
+                                            chunk.dataSize) != android::NO_ERROR) {
                     ALOGE("Failed to set sent parcel data.");
                     return std::nullopt;
                 }
                 break;
             }
             case REPLY_PARCEL_CHUNK: {
-                if (t.mReply.setData(reinterpret_cast<const unsigned char*>(payloadMap),
-                                     chunk.dataSize) != android::NO_ERROR) {
+                if (t.mReplyDataOnly.setData(reinterpret_cast<const unsigned char*>(payloadMap),
+                                             chunk.dataSize) != android::NO_ERROR) {
                     ALOGE("Failed to set reply parcel data.");
                     return std::nullopt;
                 }
                 break;
             }
+            case DATA_PARCEL_OBJECT_CHUNK: {
+                const uint64_t* objects = reinterpret_cast<const uint64_t*>(payloadMap);
+                size_t metaDataSize = (chunk.dataSize / sizeof(uint64_t));
+                ALOGI("Total objects found in saved parcel %zu", metaDataSize);
+                for (size_t index = 0; index < metaDataSize; ++index) {
+                    t.mData.mSentObjectData.push_back(objects[index]);
+                }
+                break;
+            }
             case END_CHUNK:
                 break;
             default:
@@ -343,14 +362,26 @@
         return UNKNOWN_ERROR;
     }
 
-    if (NO_ERROR != writeChunk(fd, DATA_PARCEL_CHUNK, mSent.dataBufferSize(), mSent.data())) {
+    if (NO_ERROR !=
+        writeChunk(fd, DATA_PARCEL_CHUNK, mSentDataOnly.dataBufferSize(), mSentDataOnly.data())) {
         ALOGE("Failed to write sent Parcel to fd %d", fd.get());
         return UNKNOWN_ERROR;
     }
-    if (NO_ERROR != writeChunk(fd, REPLY_PARCEL_CHUNK, mReply.dataBufferSize(), mReply.data())) {
+
+    if (NO_ERROR !=
+        writeChunk(fd, REPLY_PARCEL_CHUNK, mReplyDataOnly.dataBufferSize(),
+                   mReplyDataOnly.data())) {
         ALOGE("Failed to write reply Parcel to fd %d", fd.get());
         return UNKNOWN_ERROR;
     }
+
+    if (NO_ERROR !=
+        writeChunk(fd, DATA_PARCEL_OBJECT_CHUNK, mData.mSentObjectData.size() * sizeof(uint64_t),
+                   reinterpret_cast<const uint8_t*>(mData.mSentObjectData.data()))) {
+        ALOGE("Failed to write sent parcel object metadata to fd %d", fd.get());
+        return UNKNOWN_ERROR;
+    }
+
     if (NO_ERROR != writeChunk(fd, END_CHUNK, 0, NULL)) {
         ALOGE("Failed to write end chunk to fd %d", fd.get());
         return UNKNOWN_ERROR;
@@ -384,10 +415,14 @@
     return mData.mHeader.version;
 }
 
+const std::vector<uint64_t>& RecordedTransaction::getObjectOffsets() const {
+    return mData.mSentObjectData;
+}
+
 const Parcel& RecordedTransaction::getDataParcel() const {
-    return mSent;
+    return mSentDataOnly;
 }
 
 const Parcel& RecordedTransaction::getReplyParcel() const {
-    return mReply;
+    return mReplyDataOnly;
 }
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 55167a7..486bdfb 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -207,6 +207,8 @@
     return NAME_NOT_FOUND;
 }
 
+void* openDeclaredPassthroughHal(const String16& interface, const String16& instance, int flag);
+
 bool checkCallingPermission(const String16& permission);
 bool checkCallingPermission(const String16& permission,
                             int32_t* outPid, int32_t* outUid);
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 09da6e3..d7096d8 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -55,6 +55,9 @@
 class TextOutput;
 namespace binder {
 class Status;
+namespace debug {
+class RecordedTransaction;
+}
 }
 
 class Parcel {
@@ -1443,6 +1446,9 @@
     // TODO(b/202029388): Remove 'getBlobAshmemSize' once no prebuilts reference
     // this
     size_t getBlobAshmemSize() const;
+
+    // Needed so that we can save object metadata to the disk
+    friend class android::binder::debug::RecordedTransaction;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/RecordedTransaction.h b/libs/binder/include/binder/RecordedTransaction.h
index 505c199..f0bee7f 100644
--- a/libs/binder/include/binder/RecordedTransaction.h
+++ b/libs/binder/include/binder/RecordedTransaction.h
@@ -50,6 +50,7 @@
     uint32_t getVersion() const;
     const Parcel& getDataParcel() const;
     const Parcel& getReplyParcel() const;
+    const std::vector<uint64_t>& getObjectOffsets() const;
 
 private:
     RecordedTransaction() = default;
@@ -75,10 +76,11 @@
     struct MovableData { // movable
         TransactionHeader mHeader;
         std::string mInterfaceName;
+        std::vector<uint64_t> mSentObjectData; /* Object Offsets */
     };
     MovableData mData;
-    Parcel mSent;
-    Parcel mReply;
+    Parcel mSentDataOnly;
+    Parcel mReplyDataOnly;
 };
 
 } // namespace binder::debug
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 316a79c..a905dff 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -243,6 +243,20 @@
         __INTRODUCED_IN(__ANDROID_API_U__);
 
 /**
+ * Opens a declared passthrough HAL.
+ *
+ * \param instance identifier of the passthrough service (e.g. "mapper")
+ * \param instance identifier of the implemenatation (e.g. "default")
+ * \param flag passed to dlopen()
+ *
+ * \return the result of dlopen of the specified HAL
+ */
+void* AServiceManager_openDeclaredPassthroughHal(const char* interface, const char* instance,
+                                                 int flag)
+        // TODO(b/302113279) use __INTRODUCED_LLNDK for vendor variants
+        __INTRODUCED_IN(__ANDROID_API_V__);
+
+/**
  * Prevent lazy services without client from shutting down their process
  *
  * This should only be used if it is every eventually set to false. If a
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 0843a8e..de624e4 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -204,6 +204,7 @@
     APersistableBundle_getDoubleVectorKeys;
     APersistableBundle_getStringVectorKeys;
     APersistableBundle_getPersistableBundleKeys;
+    AServiceManager_openDeclaredPassthroughHal; # systemapi llndk
 };
 
 LIBBINDER_NDK_PLATFORM {
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index 3bfdc59..5529455 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -200,6 +200,13 @@
         callback(String8(updatableViaApex.value()).c_str(), context);
     }
 }
+void* AServiceManager_openDeclaredPassthroughHal(const char* interface, const char* instance,
+                                                 int flag) {
+    LOG_ALWAYS_FATAL_IF(interface == nullptr, "interface == nullptr");
+    LOG_ALWAYS_FATAL_IF(instance == nullptr, "instance == nullptr");
+
+    return openDeclaredPassthroughHal(String16(interface), String16(instance), flag);
+}
 void AServiceManager_forceLazyServicesPersist(bool persist) {
     auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
     serviceRegistrar.forcePersist(persist);
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index cab1a60..966ec95 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -984,7 +984,7 @@
         return generatedFlaggedService(test_flags, kBinderNdkUnitTestServiceFlagged);
     }
 
-    ABinderProcess_setThreadPoolMaxThreadCount(1);  // to receive death notifications/callbacks
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
     ABinderProcess_startThreadPool();
 
     return RUN_ALL_TESTS();
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index dd2be94..2f0987f 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -69,10 +69,14 @@
 cc_test {
     name: "binderRecordReplayTest",
     srcs: ["binderRecordReplayTest.cpp"],
+    cflags: [
+        "-DBINDER_WITH_KERNEL_IPC",
+    ],
     shared_libs: [
         "libbinder",
         "libcutils",
         "libutils",
+        "liblog",
     ],
     static_libs: [
         "binderRecordReplayTestIface-cpp",
@@ -96,6 +100,14 @@
             enabled: true,
             platform_apis: true,
         },
+
+        // TODO: switch from FileDescriptor to ParcelFileDescriptor
+        ndk: {
+            enabled: false,
+        },
+        rust: {
+            enabled: false,
+        },
     },
 }
 
diff --git a/libs/binder/tests/IBinderRecordReplayTest.aidl b/libs/binder/tests/IBinderRecordReplayTest.aidl
index bd6b03c..29267e9 100644
--- a/libs/binder/tests/IBinderRecordReplayTest.aidl
+++ b/libs/binder/tests/IBinderRecordReplayTest.aidl
@@ -69,4 +69,10 @@
 
     void setSingleDataParcelableArray(in SingleDataParcelable[] input);
     SingleDataParcelable[] getSingleDataParcelableArray();
+
+    void setBinder(in IBinder binder);
+    IBinder getBinder();
+
+    void setFileDescriptor(in FileDescriptor fd);
+    FileDescriptor getFileDescriptor();
 }
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index cb1a1ee..0ee96e7 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -70,7 +70,7 @@
 }
 
 static ::testing::AssertionResult IsPageAligned(void *buf) {
-    if (((unsigned long)buf & ((unsigned long)PAGE_SIZE - 1)) == 0)
+    if (((unsigned long)buf & ((unsigned long)getpagesize() - 1)) == 0)
         return ::testing::AssertionSuccess();
     else
         return ::testing::AssertionFailure() << buf << " is not page aligned";
diff --git a/libs/binder/tests/binderRecordReplayTest.cpp b/libs/binder/tests/binderRecordReplayTest.cpp
index 73c0a94..b975fad 100644
--- a/libs/binder/tests/binderRecordReplayTest.cpp
+++ b/libs/binder/tests/binderRecordReplayTest.cpp
@@ -24,7 +24,10 @@
 #include <binder/RecordedTransaction.h>
 #include <binder/unique_fd.h>
 
+#include <cutils/ashmem.h>
+
 #include <fuzzbinder/libbinder_driver.h>
+#include <fuzzbinder/random_binder.h>
 #include <fuzzer/FuzzedDataProvider.h>
 #include <fuzzseeds/random_parcel_seeds.h>
 
@@ -37,6 +40,7 @@
 
 using namespace android;
 using android::generateSeedsFromRecording;
+using android::RandomBinder;
 using android::binder::borrowed_fd;
 using android::binder::Status;
 using android::binder::unique_fd;
@@ -44,6 +48,7 @@
 using parcelables::SingleDataParcelable;
 
 const String16 kServerName = String16("binderRecordReplay");
+extern std::string kRandomInterfaceName;
 
 #define GENERATE_GETTER_SETTER_PRIMITIVE(name, T) \
     Status set##name(T input) {                   \
@@ -81,6 +86,7 @@
 
     GENERATE_GETTER_SETTER(String, String16);
     GENERATE_GETTER_SETTER(SingleDataParcelable, SingleDataParcelable);
+    GENERATE_GETTER_SETTER(Binder, sp<IBinder>);
 
     GENERATE_GETTER_SETTER(BooleanArray, std::vector<bool>);
     GENERATE_GETTER_SETTER(ByteArray, std::vector<uint8_t>);
@@ -91,12 +97,22 @@
     GENERATE_GETTER_SETTER(DoubleArray, std::vector<double>);
     GENERATE_GETTER_SETTER(StringArray, std::vector<::android::String16>);
     GENERATE_GETTER_SETTER(SingleDataParcelableArray, std::vector<SingleDataParcelable>);
+
+    Status setFileDescriptor(unique_fd input) {
+        mFd = std::move(unique_fd(dup(input)));
+        return Status::ok();
+    }
+
+    Status getFileDescriptor(unique_fd* output) {
+        *output = std::move(unique_fd(dup(mFd)));
+        return Status::ok();
+    }
+    unique_fd mFd;
 };
 
 std::vector<uint8_t> retrieveData(borrowed_fd fd) {
     struct stat fdStat;
     EXPECT_TRUE(fstat(fd.get(), &fdStat) != -1);
-    EXPECT_TRUE(fdStat.st_size != 0);
 
     std::vector<uint8_t> buffer(fdStat.st_size);
     auto readResult = android::base::ReadFully(fd, buffer.data(), fdStat.st_size);
@@ -115,6 +131,7 @@
     // Read the data which has been written to seed corpus
     ASSERT_EQ(0, lseek(seedFd.get(), 0, SEEK_SET));
     std::vector<uint8_t> seedData = retrieveData(seedFd);
+    EXPECT_TRUE(seedData.size() != 0);
 
     // use fuzzService to replay the corpus
     FuzzedDataProvider provider(seedData.data(), seedData.size());
@@ -148,7 +165,14 @@
     template <typename T, typename U>
     void recordReplay(Status (IBinderRecordReplayTest::*set)(T), U recordedValue,
                       Status (IBinderRecordReplayTest::*get)(U*), U changedValue) {
-        auto replayFunctions = {&replayBinder, &replayFuzzService};
+        using ReplayFunc = decltype(&replayFuzzService);
+        vector<ReplayFunc> replayFunctions = {&replayFuzzService};
+        if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) {
+            // Parcel retrieved from record replay doesn't have object information. use it for
+            // replaying primitive types only.
+            replayFunctions.push_back(&replayBinder);
+        }
+
         for (auto replayFunc : replayFunctions) {
             unique_fd fd(open("/data/local/tmp/binderRecordReplayTest.rec",
                               O_RDWR | O_CREAT | O_CLOEXEC, 0666));
@@ -156,7 +180,7 @@
 
             // record a transaction
             mBpBinder->startRecordingBinder(fd);
-            auto status = (*mInterface.*set)(recordedValue);
+            auto status = (*mInterface.*set)(std::move(recordedValue));
             EXPECT_TRUE(status.isOk());
             mBpBinder->stopRecordingBinder();
 
@@ -164,16 +188,22 @@
             U output;
             status = (*mInterface.*get)(&output);
             EXPECT_TRUE(status.isOk());
-            EXPECT_EQ(output, recordedValue);
+
+            // Expect this equal only if types are primitives
+            if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) {
+                EXPECT_EQ(output, recordedValue);
+            }
 
             // write over the existing state
-            status = (*mInterface.*set)(changedValue);
+            status = (*mInterface.*set)(std::move(changedValue));
             EXPECT_TRUE(status.isOk());
 
             status = (*mInterface.*get)(&output);
             EXPECT_TRUE(status.isOk());
 
-            EXPECT_EQ(output, changedValue);
+            if (!std::is_same_v<U, unique_fd> && !std::is_same_v<U, sp<IBinder>>) {
+                EXPECT_EQ(output, changedValue);
+            }
 
             // replay transaction
             ASSERT_EQ(0, lseek(fd.get(), 0, SEEK_SET));
@@ -186,7 +216,23 @@
 
             status = (*mInterface.*get)(&output);
             EXPECT_TRUE(status.isOk());
-            EXPECT_EQ(output, recordedValue);
+
+            // FDs and binders will be replaced with random fd and random binders
+            if constexpr (std::is_same_v<U, unique_fd>) {
+                // verify that replayed fd is /dev/null. This is being replayed from random_fd.cpp
+                // and choosing /dav/null while generating seed in binder2corpus
+                std::string fdPath = "/proc/self/fd/" + std::to_string(output.get());
+                char path[PATH_MAX];
+                ASSERT_GT(readlink(fdPath.c_str(), path, sizeof(path)), 0);
+                EXPECT_EQ(strcmp("/dev/null", path), 0);
+            } else if constexpr (std::is_same_v<U, sp<IBinder>>) {
+                // This is binder is replayed from random_binder.cpp using seed data which writes
+                // this interface.
+                EXPECT_EQ(String16(kRandomInterfaceName.c_str(), kRandomInterfaceName.size()),
+                          output->getInterfaceDescriptor());
+            } else {
+                ASSERT_EQ(recordedValue, output);
+            }
         }
     }
 
@@ -319,6 +365,32 @@
                  &IBinderRecordReplayTest::getSingleDataParcelableArray, changed);
 }
 
+TEST_F(BinderRecordReplayTest, ReplayBinder) {
+    vector<uint8_t> data = {0x8A, 0x19, 0x0D, 0x44, 0x37, 0x0D, 0x38, 0x5E, 0x9B, 0xAA, 0xF3, 0xDA};
+    sp<IBinder> saved = new RandomBinder(String16("random_interface"), std::move(data));
+    sp<IBinder> changed = IInterface::asBinder(defaultServiceManager());
+    recordReplay(&IBinderRecordReplayTest::setBinder, saved, &IBinderRecordReplayTest::getBinder,
+                 changed);
+}
+
+TEST_F(BinderRecordReplayTest, ReplayFd) {
+    // Write something to both fds we are setting
+    unique_fd saved(open("/data/local/tmp/test_fd", O_RDWR | O_CREAT | O_CLOEXEC, 0666));
+    std::string contentSaved = "This will be never read again for recorded fd!";
+    CHECK(android::base::WriteFully(saved, contentSaved.data(), contentSaved.size()))
+            << saved.get();
+
+    unique_fd changed(open("/data/local/tmp/test_des", O_RDWR | O_CREAT | O_CLOEXEC, 0666));
+    std::string contentChanged = "This will be never read again from changed fd!";
+    CHECK(android::base::WriteFully(changed, contentChanged.data(), contentChanged.size()))
+            << changed.get();
+
+    // When fds are replayed, it will be replaced by /dev/null..reading from it should yield
+    // null data
+    recordReplay(&IBinderRecordReplayTest::setFileDescriptor, std::move(unique_fd(dup(saved))),
+                 &IBinderRecordReplayTest::getFileDescriptor, std::move(unique_fd(dup(changed))));
+}
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
 
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
index 83db6c9..fbab8f0 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -131,6 +131,13 @@
         "libcutils",
         "libutils",
     ],
+    static_libs: [
+        "libbinder_random_parcel",
+    ],
+    include_dirs: [
+        "bionic/libc/kernel/android/uapi/",
+        "bionic/libc/kernel/uapi/",
+    ],
     local_include_dirs: [
         "include_random_parcel_seeds",
     ],
@@ -140,8 +147,12 @@
 cc_binary_host {
     name: "binder2corpus",
     static_libs: [
+        "libbinder_random_parcel",
         "libbinder_random_parcel_seeds",
     ],
+    cflags: [
+        "-DBINDER_WITH_KERNEL_IPC",
+    ],
     srcs: [
         "binder2corpus/binder2corpus.cpp",
     ],
@@ -149,5 +160,6 @@
         "libbase",
         "libbinder",
         "libutils",
+        "libcutils",
     ],
 }
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h
index 8fc9263..7a1688b 100644
--- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h
@@ -16,11 +16,25 @@
 
 #pragma once
 
+#include <binder/Binder.h>
 #include <binder/IBinder.h>
 #include <fuzzer/FuzzedDataProvider.h>
 
 namespace android {
 
+class RandomBinder : public BBinder {
+public:
+    RandomBinder(const String16& descriptor, std::vector<uint8_t>&& bytes);
+    const String16& getInterfaceDescriptor() const override;
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
+
+private:
+    String16 mDescriptor;
+    // note may not all be used
+    std::vector<uint8_t> mBytes;
+    FuzzedDataProvider mProvider;
+};
+
 // Get a random binder object for use in fuzzing.
 //
 // May return nullptr.
diff --git a/libs/binder/tests/parcel_fuzzer/random_binder.cpp b/libs/binder/tests/parcel_fuzzer/random_binder.cpp
index 8a1fecb..f41c35b 100644
--- a/libs/binder/tests/parcel_fuzzer/random_binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_binder.cpp
@@ -21,56 +21,52 @@
 #include <binder/IInterface.h>
 #include <binder/IServiceManager.h>
 
+size_t kRandomInterfaceLength = 50;
 namespace android {
 
-class RandomBinder : public BBinder {
-public:
-    RandomBinder(const String16& descriptor, std::vector<uint8_t>&& bytes)
-          : mDescriptor(descriptor),
-            mBytes(std::move(bytes)),
-            mProvider(mBytes.data(), mBytes.size()) {}
-    const String16& getInterfaceDescriptor() const override { return mDescriptor; }
+RandomBinder::RandomBinder(const String16& descriptor, std::vector<uint8_t>&& bytes)
+      : mDescriptor(descriptor),
+        mBytes(std::move(bytes)),
+        mProvider(mBytes.data(), mBytes.size()) {}
 
-    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override {
-        (void)code;
-        (void)data;
-        (void)reply;
-        (void)flags; // note - for maximum coverage even ignore if oneway
+const String16& RandomBinder::getInterfaceDescriptor() const {
+    return mDescriptor;
+}
 
-        if (mProvider.ConsumeBool()) {
-            return mProvider.ConsumeIntegral<status_t>();
-        }
+status_t RandomBinder::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                  uint32_t flags) {
+    (void)code;
+    (void)data;
+    (void)reply;
+    (void)flags; // note - for maximum coverage even ignore if oneway
 
-        if (reply == nullptr) return OK;
-
-        // TODO: things we could do to increase state space
-        // - also pull FDs and binders from 'data'
-        //     (optionally combine these into random parcel 'options')
-        // - also pull FDs and binders from random parcel 'options'
-        RandomParcelOptions options;
-
-        // random output
-        std::vector<uint8_t> subData = mProvider.ConsumeBytes<uint8_t>(
-                mProvider.ConsumeIntegralInRange<size_t>(0, mProvider.remaining_bytes()));
-        fillRandomParcel(reply, FuzzedDataProvider(subData.data(), subData.size()), &options);
-
-        return OK;
+    if (mProvider.ConsumeBool()) {
+        return mProvider.ConsumeIntegral<status_t>();
     }
 
-private:
-    String16 mDescriptor;
+    if (reply == nullptr) return OK;
 
-    // note may not all be used
-    std::vector<uint8_t> mBytes;
-    FuzzedDataProvider mProvider;
-};
+    // TODO: things we could do to increase state space
+    // - also pull FDs and binders from 'data'
+    //     (optionally combine these into random parcel 'options')
+    // - also pull FDs and binders from random parcel 'options'
+    RandomParcelOptions options;
+
+    // random output
+    std::vector<uint8_t> subData = mProvider.ConsumeBytes<uint8_t>(
+            mProvider.ConsumeIntegralInRange<size_t>(0, mProvider.remaining_bytes()));
+    fillRandomParcel(reply, FuzzedDataProvider(subData.data(), subData.size()), &options);
+
+    return OK;
+}
 
 sp<IBinder> getRandomBinder(FuzzedDataProvider* provider) {
     auto makeFunc = provider->PickValueInArray<const std::function<sp<IBinder>()>>({
             [&]() {
                 // descriptor is the length of a class name, e.g.
                 // "some.package.Foo"
-                std::string str = provider->ConsumeRandomLengthString(100 /*max length*/);
+                std::string str =
+                        provider->ConsumeRandomLengthString(kRandomInterfaceLength /*max length*/);
 
                 // arbitrarily consume remaining data to create a binder that can return
                 // random results - coverage guided fuzzer should ensure all of the remaining
diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 4e58dc4..62b8433 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -73,7 +73,7 @@
                         return;
                     }
 
-                    if (options->extraFds.size() > 0 && provider.ConsumeBool()) {
+                    if (provider.ConsumeBool() && options->extraFds.size() > 0) {
                         const unique_fd& fd = options->extraFds.at(
                                 provider.ConsumeIntegralInRange<size_t>(0,
                                                                         options->extraFds.size() -
@@ -102,7 +102,7 @@
                     }
 
                     sp<IBinder> binder;
-                    if (options->extraBinders.size() > 0 && provider.ConsumeBool()) {
+                    if (provider.ConsumeBool() && options->extraBinders.size() > 0) {
                         binder = options->extraBinders.at(
                                 provider.ConsumeIntegralInRange<size_t>(0,
                                                                         options->extraBinders
diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp
index 7b3c806..fd9777a 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp
@@ -14,16 +14,26 @@
  * limitations under the License.
  */
 
+#include <linux/android/binder.h>
+
 #include <android-base/logging.h>
 
+#include <binder/Parcel.h>
 #include <binder/RecordedTransaction.h>
 
 #include <fuzzseeds/random_parcel_seeds.h>
 
+#include <stack>
+#include <string>
 #include "../../file.h"
 
 using android::binder::borrowed_fd;
 using android::binder::WriteFully;
+using std::stack;
+
+extern size_t kRandomInterfaceLength;
+// Keep this in sync with max_length in random_binder.cpp while creating a RandomBinder
+std::string kRandomInterfaceName(kRandomInterfaceLength, 'i');
 
 namespace android {
 namespace impl {
@@ -66,6 +76,162 @@
 
 } // namespace impl
 
+struct ProviderMetadata {
+    size_t position;
+    size_t value;
+
+    ProviderMetadata() {
+        value = 0;
+        position = 0;
+    }
+};
+
+// Assuming current seed path is inside the fillRandomParcel function, start of the loop.
+void writeRandomBinder(borrowed_fd fd, vector<uint8_t>& fillParcelBuffer,
+                       stack<ProviderMetadata>& remainingPositions) {
+    // Choose 2 index in array
+    size_t fillFuncIndex = 2;
+    impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2),
+                              fillFuncIndex);
+
+    // navigate to getRandomBinder. provide consume bool false
+    bool flag = false;
+    impl::writeReversedBuffer(fillParcelBuffer, flag);
+
+    // selecting RandomBinder, other binders in the list are not recorded as KernelObjects
+    size_t randomBinderIndex = 0;
+    impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2),
+                              randomBinderIndex);
+
+    // write random string of length 100 in actual buffer array.
+    CHECK(WriteFully(fd, kRandomInterfaceName.c_str(), kRandomInterfaceName.size())) << fd.get();
+
+    // These will be bytes which are used inside of RandomBinder
+    // simplest path for these bytes is going to be consume bool -> return random status
+    vector<uint8_t> randomBinderBuffer;
+
+    bool returnRandomInt = true;
+    impl::writeReversedBuffer(randomBinderBuffer, returnRandomInt);
+
+    status_t randomStatus = 0;
+    impl::writeReversedBuffer(randomBinderBuffer, randomStatus);
+
+    // write integral in range to consume bytes for random binder
+    ProviderMetadata providerData;
+    providerData.position = fillParcelBuffer.size();
+    providerData.value = randomBinderBuffer.size();
+    remainingPositions.push(providerData);
+
+    // Write to fd
+    CHECK(WriteFully(fd, randomBinderBuffer.data(), randomBinderBuffer.size())) << fd.get();
+}
+
+// Assuming current seed path is inside the fillRandomParcelFunction, start of the loop.
+void writeRandomFd(vector<uint8_t>& fillParcelBuffer) {
+    // path to random fd
+    size_t fillFuncIndex = 1;
+    impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2),
+                              fillFuncIndex);
+
+    bool flag = false;
+    impl::writeReversedBuffer(fillParcelBuffer, flag);
+
+    // go for /dev/null index 1
+    size_t fdIndex = 1;
+    impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(3),
+                              fdIndex);
+}
+
+void writeParcelData(borrowed_fd fd, vector<uint8_t>& fillParcelBuffer,
+                     stack<ProviderMetadata>& remainingPositions, const uint8_t* data, size_t start,
+                     size_t length) {
+    // need to write parcel data till next offset with instructions to pick random bytes till offset
+    size_t fillFuncIndex = 0;
+    impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2),
+                              fillFuncIndex);
+
+    // provide how much bytes to read in control buffer
+    ProviderMetadata providerData;
+    providerData.position = fillParcelBuffer.size();
+    providerData.value = length;
+    remainingPositions.push(providerData);
+
+    // provide actual bytes
+    CHECK(WriteFully(fd, data + start, length)) << fd.get();
+}
+
+/**
+ *   Generate sequence of copy data, write fd and write binder instructions and required data.
+ *   Data which will be read using consumeBytes is written to fd directly. Data which is read in
+ *   form integer is consumed from rear end FuzzedDataProvider. So insert it in fillParcelBuffer and
+ *   then write to fd
+ */
+size_t regenerateParcel(borrowed_fd fd, vector<uint8_t>& fillParcelBuffer, const Parcel& p,
+                        size_t dataSize, const vector<uint64_t>& objectOffsets) {
+    stack<ProviderMetadata> remainingPositions;
+    size_t copiedDataPosition = 0;
+    const uint8_t* parcelData = p.data();
+    size_t numBinders = 0;
+    size_t numFds = 0;
+
+    for (auto offset : objectOffsets) {
+        // Check what type of object is present here
+        const flat_binder_object* flatObject =
+                reinterpret_cast<const flat_binder_object*>(parcelData + offset);
+        // Copy till the object offset
+        writeParcelData(fd, fillParcelBuffer, remainingPositions, parcelData, copiedDataPosition,
+                        offset - copiedDataPosition);
+        copiedDataPosition = offset;
+        if (flatObject->hdr.type == BINDER_TYPE_BINDER ||
+            flatObject->hdr.type == BINDER_TYPE_HANDLE) {
+            writeRandomBinder(fd, fillParcelBuffer, remainingPositions);
+            numBinders++;
+            // In case of binder, stability is written after the binder object.
+            // We want to move the copiedDataPosition further to account for this stability field
+            copiedDataPosition += sizeof(int32_t) + sizeof(flat_binder_object);
+        } else if (flatObject->hdr.type == BINDER_TYPE_FD) {
+            writeRandomFd(fillParcelBuffer);
+            numFds++;
+            copiedDataPosition += sizeof(flat_binder_object);
+        }
+    }
+
+    if (copiedDataPosition < dataSize) {
+        // copy remaining data from recorded parcel -> last Object to end of the data
+        writeParcelData(fd, fillParcelBuffer, remainingPositions, parcelData, copiedDataPosition,
+                        dataSize - copiedDataPosition);
+    }
+
+    // We need to write bytes for selecting integer within range of  0 to provide.remaining_bytes()
+    // is called.
+    size_t totalWrittenBytes = dataSize - (sizeof(flat_binder_object) * objectOffsets.size()) -
+            (sizeof(int32_t) * numBinders) +
+            (kRandomInterfaceName.size() /*Interface String*/ + sizeof(bool) + sizeof(status_t)) *
+                    numBinders;
+
+    // Code in fuzzService relies on provider.remaining_bytes() to select random bytes using
+    // consume integer. use the calculated remaining_bytes to generate byte buffer which can
+    // generate required fds and binders in fillRandomParcel function.
+    while (!remainingPositions.empty()) {
+        auto meta = remainingPositions.top();
+        remainingPositions.pop();
+        size_t remainingBytes = totalWrittenBytes + fillParcelBuffer.size() - meta.position;
+
+        vector<uint8_t> remReversedBytes;
+        impl::writeReversedBuffer(remReversedBytes, static_cast<size_t>(0), remainingBytes,
+                                  meta.value);
+        // Check the order of buffer which is being written
+        fillParcelBuffer.insert(fillParcelBuffer.end() - meta.position, remReversedBytes.begin(),
+                                remReversedBytes.end());
+    }
+
+    return totalWrittenBytes;
+}
+
+/**
+ * Current corpus format
+ * |Reserved bytes(8)|parcel data|fillParcelBuffer|integralBuffer|
+ */
 void generateSeedsFromRecording(borrowed_fd fd,
                                 const binder::debug::RecordedTransaction& transaction) {
     // Write Reserved bytes for future use
@@ -123,17 +289,9 @@
     uint8_t writeHeaderInternal = 0;
     impl::writeReversedBuffer(fillParcelBuffer, writeHeaderInternal);
 
-    // Choose to write data in parcel
-    size_t fillFuncIndex = 0;
-    impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), static_cast<size_t>(2),
-                              fillFuncIndex);
-
-    // Write parcel data size from recorded transaction
-    size_t toWrite = transaction.getDataParcel().dataBufferSize();
-    impl::writeReversedBuffer(fillParcelBuffer, static_cast<size_t>(0), toWrite, toWrite);
-
-    // Write parcel data with size towrite from recorded transaction
-    CHECK(WriteFully(fd, dataParcel.data(), toWrite)) << fd.get();
+    auto objectMetadata = transaction.getObjectOffsets();
+    size_t toWrite = regenerateParcel(fd, fillParcelBuffer, dataParcel, dataParcel.dataBufferSize(),
+                                      objectMetadata);
 
     // Write Fill Parcel buffer size in integralBuffer so that fuzzService knows size of data
     size_t subDataSize = toWrite + fillParcelBuffer.size();
diff --git a/libs/gui/Choreographer.cpp b/libs/gui/Choreographer.cpp
index 46fb068..a52f68e 100644
--- a/libs/gui/Choreographer.cpp
+++ b/libs/gui/Choreographer.cpp
@@ -116,7 +116,7 @@
     std::lock_guard<std::mutex> _l(gChoreographers.lock);
     gChoreographers.ptrs.erase(std::remove_if(gChoreographers.ptrs.begin(),
                                               gChoreographers.ptrs.end(),
-                                              [=](Choreographer* c) { return c == this; }),
+                                              [=, this](Choreographer* c) { return c == this; }),
                                gChoreographers.ptrs.end());
     // Only poke DisplayManagerGlobal to unregister if we previously registered
     // callbacks.
@@ -394,4 +394,4 @@
     return iter->second;
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 462ce6e..15e8744 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -3,6 +3,7 @@
 // Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
 // to integrate with auto-test framework.
 package {
+    default_team: "trendy_team_android_core_graphics_stack",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "frameworks_native_license"
diff --git a/libs/gui/tests/AndroidTest.xml b/libs/gui/tests/AndroidTest.xml
index 31b10d7..b4ccf87 100644
--- a/libs/gui/tests/AndroidTest.xml
+++ b/libs/gui/tests/AndroidTest.xml
@@ -18,6 +18,7 @@
         <option name="cleanup" value="true" />
         <option name="push" value="libgui_test->/data/local/tmp/libgui_test" />
     </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
       <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
       <option name="screen-always-on" value="on" />
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 022dfad..a67ed29 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -221,7 +221,7 @@
         "liblog",
         "libPlatformProperties",
         "libtinyxml2",
-        "libvintf",
+        "libz", // needed by libkernelconfigs
     ],
 
     ldflags: [
@@ -238,6 +238,7 @@
         "inputconstants-cpp",
         "libui-types",
         "libtflite_static",
+        "libkernelconfigs",
     ],
 
     whole_static_libs: [
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 9c7c0c1..ccc8323 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -20,12 +20,14 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <ftl/enum.h>
 #include <gui/constants.h>
 #include <input/InputDevice.h>
 #include <input/InputEventLabels.h>
 
+using android::base::GetProperty;
 using android::base::StringPrintf;
 
 namespace android {
@@ -96,21 +98,22 @@
 
     // Treblized input device config files will be located /product/usr, /system_ext/usr,
     // /odm/usr or /vendor/usr.
-    // These files may also be in the com.android.input.config APEX.
-    const char* rootsForPartition[]{
-            "/product",
-            "/system_ext",
-            "/odm",
-            "/vendor",
-            "/apex/com.android.input.config/etc",
-            getenv("ANDROID_ROOT"),
+    std::vector<std::string> pathPrefixes{
+            "/product/usr/",
+            "/system_ext/usr/",
+            "/odm/usr/",
+            "/vendor/usr/",
     };
-    for (size_t i = 0; i < size(rootsForPartition); i++) {
-        if (rootsForPartition[i] == nullptr) {
-            continue;
-        }
-        path = rootsForPartition[i];
-        path += "/usr/";
+    // These files may also be in the APEX pointed by input_device.config_file.apex sysprop.
+    if (auto apex = GetProperty("input_device.config_file.apex", ""); !apex.empty()) {
+        pathPrefixes.push_back("/apex/" + apex + "/etc/usr/");
+    }
+    // ANDROID_ROOT may not be set on host
+    if (auto android_root = getenv("ANDROID_ROOT"); android_root != nullptr) {
+        pathPrefixes.push_back(std::string(android_root) + "/usr/");
+    }
+    for (const auto& prefix : pathPrefixes) {
+        path = prefix;
         appendInputDeviceConfigurationFileRelativePath(path, name, type);
 #if DEBUG_PROBE
         ALOGD("Probing for system provided input device configuration file: path='%s'",
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index 3c1ae3e..ab8c341 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -27,8 +27,7 @@
 #include <utils/Timers.h>
 #include <utils/Tokenizer.h>
 #if defined(__ANDROID__)
-#include <vintf/RuntimeInfo.h>
-#include <vintf/VintfObject.h>
+#include <vintf/KernelConfigs.h>
 #endif
 
 #include <cstdlib>
@@ -98,12 +97,10 @@
 
 bool kernelConfigsArePresent(const std::set<std::string>& configs) {
 #if defined(__ANDROID__)
-    std::shared_ptr<const android::vintf::RuntimeInfo> runtimeInfo =
-            android::vintf::VintfObject::GetInstance()->getRuntimeInfo(
-                    vintf::RuntimeInfo::FetchFlag::CONFIG_GZ);
-    LOG_ALWAYS_FATAL_IF(runtimeInfo == nullptr, "Kernel configs could not be fetched");
+    std::map<std::string, std::string> kernelConfigs;
+    const status_t result = android::kernelconfigs::LoadKernelConfigs(&kernelConfigs);
+    LOG_ALWAYS_FATAL_IF(result != OK, "Kernel configs could not be fetched");
 
-    const std::map<std::string, std::string>& kernelConfigs = runtimeInfo->kernelConfigs();
     for (const std::string& requiredConfig : configs) {
         const auto configIt = kernelConfigs.find(requiredConfig);
         if (configIt == kernelConfigs.end()) {
diff --git a/libs/input/input_verifier.rs b/libs/input/input_verifier.rs
index f8dda3c..767865c 100644
--- a/libs/input/input_verifier.rs
+++ b/libs/input/input_verifier.rs
@@ -184,7 +184,7 @@
         logger::init(
             logger::Config::default()
                 .with_tag_on_device("InputVerifier")
-                .with_min_level(log::Level::Trace),
+                .with_max_level(log::LevelFilter::Trace),
         );
         Self { name: name.to_owned(), touching_pointer_ids_by_device: HashMap::new() }
     }
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index e7224ff..3fc7d9d 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -36,8 +36,10 @@
         "libgmock",
         "libgui_window_info_static",
         "libinput",
+        "libkernelconfigs",
         "libtflite_static",
         "libui-types",
+        "libz", // needed by libkernelconfigs
     ],
     cflags: [
         "-Wall",
@@ -61,7 +63,6 @@
         "libPlatformProperties",
         "libtinyxml2",
         "libutils",
-        "libvintf",
     ],
     data: [
         "data/*",
diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs
index aab7df0..22ad834 100644
--- a/libs/nativewindow/rust/src/lib.rs
+++ b/libs/nativewindow/rust/src/lib.rs
@@ -16,6 +16,8 @@
 
 extern crate nativewindow_bindgen as ffi;
 
+pub mod surface;
+
 pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};
 
 use binder::{
@@ -210,7 +212,7 @@
 }
 
 impl Debug for HardwareBuffer {
-    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
         f.debug_struct("HardwareBuffer").field("id", &self.id()).finish()
     }
 }
diff --git a/libs/nativewindow/rust/src/surface.rs b/libs/nativewindow/rust/src/surface.rs
new file mode 100644
index 0000000..25fea80
--- /dev/null
+++ b/libs/nativewindow/rust/src/surface.rs
@@ -0,0 +1,143 @@
+// Copyright (C) 2024 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.
+
+//! Rust wrapper for `ANativeWindow` and related types.
+
+use binder::{
+    binder_impl::{BorrowedParcel, UnstructuredParcelable},
+    impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
+    unstable_api::{status_result, AsNative},
+    StatusCode,
+};
+use nativewindow_bindgen::{
+    AHardwareBuffer_Format, ANativeWindow, ANativeWindow_acquire, ANativeWindow_getFormat,
+    ANativeWindow_getHeight, ANativeWindow_getWidth, ANativeWindow_readFromParcel,
+    ANativeWindow_release, ANativeWindow_writeToParcel,
+};
+use std::error::Error;
+use std::fmt::{self, Debug, Display, Formatter};
+use std::ptr::{null_mut, NonNull};
+
+/// Wrapper around an opaque C `ANativeWindow`.
+#[derive(PartialEq, Eq)]
+pub struct Surface(NonNull<ANativeWindow>);
+
+impl Surface {
+    /// Returns the current width in pixels of the window surface.
+    pub fn width(&self) -> Result<u32, ErrorCode> {
+        // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
+        // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
+        // and we have not yet released it.
+        let width = unsafe { ANativeWindow_getWidth(self.0.as_ptr()) };
+        width.try_into().map_err(|_| ErrorCode(width))
+    }
+
+    /// Returns the current height in pixels of the window surface.
+    pub fn height(&self) -> Result<u32, ErrorCode> {
+        // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
+        // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
+        // and we have not yet released it.
+        let height = unsafe { ANativeWindow_getHeight(self.0.as_ptr()) };
+        height.try_into().map_err(|_| ErrorCode(height))
+    }
+
+    /// Returns the current pixel format of the window surface.
+    pub fn format(&self) -> Result<AHardwareBuffer_Format::Type, ErrorCode> {
+        // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
+        // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
+        // and we have not yet released it.
+        let format = unsafe { ANativeWindow_getFormat(self.0.as_ptr()) };
+        format.try_into().map_err(|_| ErrorCode(format))
+    }
+}
+
+impl Drop for Surface {
+    fn drop(&mut self) {
+        // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
+        // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
+        // and we have not yet released it.
+        unsafe { ANativeWindow_release(self.0.as_ptr()) }
+    }
+}
+
+impl Debug for Surface {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        f.debug_struct("Surface")
+            .field("width", &self.width())
+            .field("height", &self.height())
+            .field("format", &self.format())
+            .finish()
+    }
+}
+
+impl Clone for Surface {
+    fn clone(&self) -> Self {
+        // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
+        // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
+        // and we have not yet released it.
+        unsafe { ANativeWindow_acquire(self.0.as_ptr()) };
+        Self(self.0)
+    }
+}
+
+impl UnstructuredParcelable for Surface {
+    fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
+        let status =
+        // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because
+        // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel`
+        // and we have not yet released it.
+        unsafe { ANativeWindow_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) };
+        status_result(status)
+    }
+
+    fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
+        let mut buffer = null_mut();
+
+        let status =
+        // SAFETY: Both pointers must be valid because they are obtained from references.
+        // `ANativeWindow_readFromParcel` doesn't store them or do anything else special
+        // with them. If it returns success then it will have allocated a new
+        // `ANativeWindow` and incremented the reference count, so we can use it until we
+        // release it.
+            unsafe { ANativeWindow_readFromParcel(parcel.as_native(), &mut buffer) };
+
+        status_result(status)?;
+
+        Ok(Self(
+            NonNull::new(buffer)
+                .expect("ANativeWindow_readFromParcel returned success but didn't allocate buffer"),
+        ))
+    }
+}
+
+impl_deserialize_for_unstructured_parcelable!(Surface);
+impl_serialize_for_unstructured_parcelable!(Surface);
+
+// SAFETY: The underlying *ANativeWindow can be moved between threads.
+unsafe impl Send for Surface {}
+
+// SAFETY: The underlying *ANativeWindow can be used from multiple threads concurrently.
+unsafe impl Sync for Surface {}
+
+/// An error code returned by methods on [`Surface`].
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct ErrorCode(i32);
+
+impl Error for ErrorCode {}
+
+impl Display for ErrorCode {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        write!(f, "Error {}", self.0)
+    }
+}
diff --git a/libs/nativewindow/rust/sys/nativewindow_bindings.h b/libs/nativewindow/rust/sys/nativewindow_bindings.h
index 4525a42..5689f7d 100644
--- a/libs/nativewindow/rust/sys/nativewindow_bindings.h
+++ b/libs/nativewindow/rust/sys/nativewindow_bindings.h
@@ -19,3 +19,4 @@
 #include <android/hardware_buffer_aidl.h>
 #include <android/hdr_metadata.h>
 #include <android/native_window.h>
+#include <android/native_window_aidl.h>
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index d71e55f..a733fd0 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -1022,7 +1022,7 @@
                                                   .fakeOutputDataspace = fakeDataspace}));
 
             // Turn on dithering when dimming beyond this (arbitrary) threshold...
-            static constexpr float kDimmingThreshold = 0.2f;
+            static constexpr float kDimmingThreshold = 0.9f;
             // ...or we're rendering an HDR layer down to an 8-bit target
             // Most HDR standards require at least 10-bits of color depth for source content, so we
             // can just extract the transfer function rather than dig into precise gralloc layout.
diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp
index 16ed82a..82e5427 100644
--- a/libs/ui/DisplayIdentification.cpp
+++ b/libs/ui/DisplayIdentification.cpp
@@ -21,6 +21,7 @@
 #include <cctype>
 #include <numeric>
 #include <optional>
+#include <span>
 
 #include <log/log.h>
 
@@ -46,6 +47,7 @@
     return val ^ (val >> 47);
 }
 
+__attribute__((no_sanitize("unsigned-integer-overflow")))
 uint64_t hash64Len16(uint64_t u, uint64_t v) {
     constexpr uint64_t kMul = 0x9ddfea08eb382d69;
     uint64_t a = (u ^ v) * kMul;
@@ -56,6 +58,7 @@
     return b;
 }
 
+__attribute__((no_sanitize("unsigned-integer-overflow")))
 uint64_t hash64Len0To16(const char* s, uint64_t len) {
     constexpr uint64_t k2 = 0x9ae16a3b2f90404f;
     constexpr uint64_t k3 = 0xc949d7c7509e6557;
@@ -81,7 +84,7 @@
     return k2;
 }
 
-using byte_view = std::basic_string_view<uint8_t>;
+using byte_view = std::span<const uint8_t>;
 
 constexpr size_t kEdidBlockSize = 128;
 constexpr size_t kEdidHeaderLength = 5;
@@ -89,7 +92,8 @@
 constexpr uint16_t kVirtualEdidManufacturerId = 0xffffu;
 
 std::optional<uint8_t> getEdidDescriptorType(const byte_view& view) {
-    if (view.size() < kEdidHeaderLength || view[0] || view[1] || view[2] || view[4]) {
+    if (static_cast<size_t>(view.size()) < kEdidHeaderLength || view[0] || view[1] || view[2] ||
+        view[4]) {
         return {};
     }
 
@@ -164,7 +168,7 @@
         constexpr size_t kDataBlockHeaderSize = 1;
         const size_t dataBlockSize = bodyLength + kDataBlockHeaderSize;
 
-        if (block.size() < dataBlockOffset + dataBlockSize) {
+        if (static_cast<size_t>(block.size()) < dataBlockOffset + dataBlockSize) {
             ALOGW("Invalid EDID: CEA 861 data block is truncated.");
             break;
         }
@@ -264,7 +268,7 @@
     }
 
     byte_view view(edid.data(), edid.size());
-    view.remove_prefix(kDescriptorOffset);
+    view = view.subspan(kDescriptorOffset);
 
     std::string_view displayName;
     std::string_view serialNumber;
@@ -274,13 +278,13 @@
     constexpr size_t kDescriptorLength = 18;
 
     for (size_t i = 0; i < kDescriptorCount; i++) {
-        if (view.size() < kDescriptorLength) {
+        if (static_cast<size_t>(view.size()) < kDescriptorLength) {
             break;
         }
 
         if (const auto type = getEdidDescriptorType(view)) {
             byte_view descriptor(view.data(), kDescriptorLength);
-            descriptor.remove_prefix(kEdidHeaderLength);
+            descriptor = descriptor.subspan(kEdidHeaderLength);
 
             switch (*type) {
                 case 0xfc:
@@ -295,7 +299,7 @@
             }
         }
 
-        view.remove_prefix(kDescriptorLength);
+        view = view.subspan(kDescriptorLength);
     }
 
     std::string_view modelString = displayName;
@@ -327,8 +331,8 @@
         const size_t numExtensions = edid[kNumExtensionsOffset];
         view = byte_view(edid.data(), edid.size());
         for (size_t blockNumber = 1; blockNumber <= numExtensions; blockNumber++) {
-            view.remove_prefix(kEdidBlockSize);
-            if (view.size() < kEdidBlockSize) {
+            view = view.subspan(kEdidBlockSize);
+            if (static_cast<size_t>(view.size()) < kEdidBlockSize) {
                 ALOGW("Invalid EDID: block %zu is truncated.", blockNumber);
                 break;
             }
@@ -399,4 +403,4 @@
     return hash64Len0To16(sv.data(), len);
 }
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/ui/Gralloc5.cpp b/libs/ui/Gralloc5.cpp
index c3b2d3d..123bef4 100644
--- a/libs/ui/Gralloc5.cpp
+++ b/libs/ui/Gralloc5.cpp
@@ -83,10 +83,18 @@
             return nullptr;
         }
 
-        std::string lib_name = "mapper." + mapperSuffix + ".so";
-        void *so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
+        void* so = nullptr;
+        // TODO(b/322384429) switch this to __ANDROID_API_V__ when V is finalized
+        // TODO(b/302113279) use __ANDROID_VENDOR_API__ for vendor variant
+        if (__builtin_available(android __ANDROID_API_FUTURE__, *)) {
+            so = AServiceManager_openDeclaredPassthroughHal("mapper", mapperSuffix.c_str(),
+                                                            RTLD_LOCAL | RTLD_NOW);
+        } else {
+            std::string lib_name = "mapper." + mapperSuffix + ".so";
+            so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
+        }
         if (!so) {
-            ALOGE("Failed to load %s", lib_name.c_str());
+            ALOGE("Failed to load mapper.%s.so", mapperSuffix.c_str());
         }
         return so;
     }();
diff --git a/libs/vibrator/fuzzer/Android.bp b/libs/vibrator/fuzzer/Android.bp
index cb063af..faa77ca 100644
--- a/libs/vibrator/fuzzer/Android.bp
+++ b/libs/vibrator/fuzzer/Android.bp
@@ -18,6 +18,7 @@
  */
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "frameworks_native_license"
diff --git a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
index 2d0a4ea..371ed89 100644
--- a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
@@ -17,12 +17,12 @@
 // C strings more efficient by avoiding unnecessary copies when remote method
 // signatures specify std::basic_string arguments or return values.
 template <typename CharT = std::string::value_type,
-          typename Traits = std::char_traits<CharT>>
+          typename Traits = std::char_traits<std::remove_cv_t<CharT>>>
 class StringWrapper {
  public:
   // Define types in the style of STL strings to support STL operators.
   typedef Traits traits_type;
-  typedef typename Traits::char_type value_type;
+  typedef CharT value_type;
   typedef std::size_t size_type;
   typedef value_type& reference;
   typedef const value_type& const_reference;
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 7fd9c3a..f73fa5d 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -22,8 +22,10 @@
 
 mkdir -p out/javax/microedition/khronos/opengles
 mkdir -p out/com/google/android/gles_jni
+mkdir -p out/android/annotation
 mkdir -p out/android/app
 mkdir -p out/android/graphics
+mkdir -p out/android/hardware
 mkdir -p out/android/view
 mkdir -p out/android/opengl
 mkdir -p out/android/content
@@ -34,18 +36,20 @@
 echo "package android.graphics;" > out/android/graphics/Canvas.java
 echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
 
+echo "package android.annotation; public @interface NonNull {}" > out/android/annotation/NonNull.java
 echo "package android.app; import android.content.pm.IPackageManager; public class AppGlobals { public static IPackageManager getPackageManager() { return null;} }" > out/android/app/AppGlobals.java
 # echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
 echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
 echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags, java.lang.String userId) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
-echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 3;};	}" > out/android/os/Build.java
+echo "package android.hardware; import android.os.ParcelFileDescriptor; public class SyncFence { public static SyncFence create(ParcelFileDescriptor w) { return null; } public static SyncFence createEmpty() { return null; } }" > out/android/hardware/SyncFence.java
+echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 0; public static final int R = 0; }; }" > out/android/os/Build.java
+echo "package android.os; public class ParcelFileDescriptor { public static ParcelFileDescriptor adoptFd(int fd) { return null; } }" > out/android/os/ParcelFileDescriptor.java
 echo "package android.os; public class UserHandle {public static String myUserId() { return \"\"; } }" > out/android/os/UserHandle.java
 echo "package android.os; public class RemoteException extends Exception {}" > out/android/os/RemoteException.java
-echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
+echo "package android.util; public class Log {public static void d(String a, String b) {} public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
 
 echo "package android.opengl; public abstract class EGLObjectHandle { public int getHandle() { return 0; } }" > out/android/opengl/EGLObjectHandle.java
 
-
 echo "package android.graphics;" > out/android/graphics/SurfaceTexture.java
 echo "public interface SurfaceTexture {}" >> out/android/graphics/SurfaceTexture.java
 echo "package android.view;" > out/android/view/SurfaceView.java
diff --git a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
index 951ecff..695b571 100644
--- a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
+++ b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
@@ -20,6 +20,7 @@
 
 import android.compat.annotation.UnsupportedAppUsage;
 import android.graphics.SurfaceTexture;
+import android.os.Build;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
diff --git a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
index b2ea041..ea55179 100644
--- a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
@@ -17,6 +17,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include "jni.h"
diff --git a/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
index 6dffac5..8e452fb 100644
--- a/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
@@ -17,6 +17,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include "jni.h"
diff --git a/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
index 523bc57..75e1704 100644
--- a/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
+++ b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
@@ -18,6 +18,11 @@
 
 package android.opengl;
 
+import android.annotation.NonNull;
+import android.hardware.SyncFence;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
 /**
  * EGL Extensions
  */
@@ -30,8 +35,44 @@
     public static final int EGL_OPENGL_ES3_BIT_KHR          = 0x0040;
     public static final int EGL_RECORDABLE_ANDROID          = 0x3142;
 
+    // EGL_ANDROID_native_fence_sync
+    public static final int EGL_SYNC_NATIVE_FENCE_ANDROID     = 0x3144;
+    public static final int EGL_SYNC_NATIVE_FENCE_FD_ANDROID  = 0x3145;
+    public static final int EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID = 0x3146;
+    public static final int EGL_NO_NATIVE_FENCE_FD_ANDROID    = -1;
+
     native private static void _nativeClassInit();
     static {
         _nativeClassInit();
     }
 
+    /**
+     * Retrieves the SyncFence for an EGLSync created with EGL_SYNC_NATIVE_FENCE_ANDROID
+     *
+     * See <a href="https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_native_fence_sync.txt">
+     *     EGL_ANDROID_native_fence_sync</a> extension for more details
+     * @param display The EGLDisplay connection
+     * @param sync The EGLSync to fetch the SyncFence from
+     * @return A SyncFence representing the native fence.
+     *       * If <sync> is not a valid sync object for <display>,
+     *         an {@link SyncFence#isValid() invalid} SyncFence is returned and an EGL_BAD_PARAMETER
+     *         error is generated.
+     *       * If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute of <sync> is
+     *         EGL_NO_NATIVE_FENCE_FD_ANDROID, an {@link SyncFence#isValid() invalid} SyncFence is
+     *         returned and an EGL_BAD_PARAMETER error is generated.
+     *       * If <display> does not match the display passed to eglCreateSync
+     *         when <sync> was created, the behaviour is undefined.
+     */
+    public static @NonNull SyncFence eglDupNativeFenceFDANDROID(@NonNull EGLDisplay display,
+            @NonNull EGLSync sync) {
+        int fd = eglDupNativeFenceFDANDROIDImpl(display, sync);
+        Log.d("EGL", "eglDupNativeFence returned " + fd);
+        if (fd >= 0) {
+            return SyncFence.create(ParcelFileDescriptor.adoptFd(fd));
+        } else {
+            return SyncFence.createEmpty();
+        }
+    }
+
+    private static native int eglDupNativeFenceFDANDROIDImpl(EGLDisplay display, EGLSync sync);
+
diff --git a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
index be8b3e3..f1f0ac5 100644
--- a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
@@ -17,6 +17,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include "jni.h"
@@ -37,25 +38,12 @@
 #include <ui/ANativeObjectBase.h>
 
 static jclass egldisplayClass;
-static jclass eglcontextClass;
 static jclass eglsurfaceClass;
-static jclass eglconfigClass;
+static jclass eglsyncClass;
 
 static jmethodID egldisplayGetHandleID;
-static jmethodID eglcontextGetHandleID;
 static jmethodID eglsurfaceGetHandleID;
-static jmethodID eglconfigGetHandleID;
-
-static jmethodID egldisplayConstructor;
-static jmethodID eglcontextConstructor;
-static jmethodID eglsurfaceConstructor;
-static jmethodID eglconfigConstructor;
-
-static jobject eglNoContextObject;
-static jobject eglNoDisplayObject;
-static jobject eglNoSurfaceObject;
-
-
+static jmethodID eglsyncGetHandleID;
 
 /* Cache method IDs each time the class is loaded. */
 
@@ -64,37 +52,14 @@
 {
     jclass egldisplayClassLocal = _env->FindClass("android/opengl/EGLDisplay");
     egldisplayClass = (jclass) _env->NewGlobalRef(egldisplayClassLocal);
-    jclass eglcontextClassLocal = _env->FindClass("android/opengl/EGLContext");
-    eglcontextClass = (jclass) _env->NewGlobalRef(eglcontextClassLocal);
     jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface");
     eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal);
-    jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
-    eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
+    jclass eglsyncClassLocal = _env->FindClass("android/opengl/EGLSync");
+    eglsyncClass = (jclass) _env->NewGlobalRef(eglsyncClassLocal);
 
     egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
-    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
     eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
-    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
-
-
-    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
-    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
-    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
-    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
-
-
-    jclass eglClass = _env->FindClass("android/opengl/EGL14");
-    jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;");
-    jobject localeglNoContextObject = _env->GetStaticObjectField(eglClass, noContextFieldID);
-    eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
-
-    jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;");
-    jobject localeglNoDisplayObject = _env->GetStaticObjectField(eglClass, noDisplayFieldID);
-    eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
-
-    jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;");
-    jobject localeglNoSurfaceObject = _env->GetStaticObjectField(eglClass, noSurfaceFieldID);
-    eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
+    eglsyncGetHandleID = _env->GetMethodID(eglsyncClass, "getNativeHandle", "()J");
 }
 
 static void *
@@ -108,24 +73,12 @@
     return reinterpret_cast<void*>(_env->CallLongMethod(obj, mid));
 }
 
-static jobject
-toEGLHandle(JNIEnv *_env, jclass cls, jmethodID con, void * handle) {
-    if (cls == eglcontextClass &&
-       (EGLContext)handle == EGL_NO_CONTEXT) {
-           return eglNoContextObject;
-    }
+// TODO: this should be generated from the .spec file, but needs to be renamed and made private
+static jint android_eglDupNativeFenceFDANDROID(JNIEnv *env, jobject, jobject dpy, jobject sync) {
+    EGLDisplay dpy_native = (EGLDisplay)fromEGLHandle(env, egldisplayGetHandleID, dpy);
+    EGLSync sync_native = (EGLSync)fromEGLHandle(env, eglsyncGetHandleID, sync);
 
-    if (cls == egldisplayClass &&
-       (EGLDisplay)handle == EGL_NO_DISPLAY) {
-           return eglNoDisplayObject;
-    }
-
-    if (cls == eglsurfaceClass &&
-       (EGLSurface)handle == EGL_NO_SURFACE) {
-           return eglNoSurfaceObject;
-    }
-
-    return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
+    return eglDupNativeFenceFDANDROID(dpy_native, sync_native);
 }
 
 // --------------------------------------------------------------------------
diff --git a/opengl/tools/glgen/stubs/egl/eglGetDisplay.java b/opengl/tools/glgen/stubs/egl/eglGetDisplay.java
index 85f743d..78b0819 100755
--- a/opengl/tools/glgen/stubs/egl/eglGetDisplay.java
+++ b/opengl/tools/glgen/stubs/egl/eglGetDisplay.java
@@ -7,7 +7,7 @@
     /**
      * {@hide}
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public static native EGLDisplay eglGetDisplay(
         long display_id
     );
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
@@ -18,6 +18,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
@@ -18,6 +18,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
@@ -18,6 +18,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
@@ -18,6 +18,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
index b2bbdf6..4004a7d 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
@@ -18,6 +18,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <GLES2/gl2.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
index b039bc9..c5bdf32 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
@@ -18,6 +18,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <GLES3/gl3.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
index dd00e92..2260a80 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
@@ -17,6 +17,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <GLES3/gl31.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
index 88e00be..130612d 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
@@ -17,6 +17,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <stdint.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
index 3e7ec8b..5446fc2 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
@@ -17,6 +17,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include <stdint.h>
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index 9cab1d6..c3534bf 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -17,6 +17,7 @@
 // This source file is automatically generated
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wunused-function"
 
 #include "jni.h"
diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp
index 4e2a6fb..e5d2b70 100644
--- a/services/inputflinger/benchmarks/Android.bp
+++ b/services/inputflinger/benchmarks/Android.bp
@@ -1,4 +1,5 @@
 package {
+    default_team: "trendy_team_input_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 1585fdd..a5564d2 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_input_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp
index 47b0824..59af493 100644
--- a/services/inputflinger/tests/fuzzers/Android.bp
+++ b/services/inputflinger/tests/fuzzers/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_input_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index c0eb36d..3cda334 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -325,7 +325,9 @@
     }
 
     mAidlComposerCallback = ndk::SharedRefBase::make<AidlIComposerCallbackWrapper>(callback);
-    AIBinder_setMinSchedulerPolicy(mAidlComposerCallback->asBinder().get(), SCHED_FIFO, 2);
+
+    ndk::SpAIBinder binder = mAidlComposerCallback->asBinder();
+    AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_FIFO, 2);
 
     const auto status = mAidlComposerClient->registerCallback(mAidlComposerCallback);
     if (!status.isOk()) {
diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp
index a468146..5437995 100644
--- a/services/vibratorservice/benchmarks/Android.bp
+++ b/services/vibratorservice/benchmarks/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp
index 3294724..be71dc2 100644
--- a/services/vibratorservice/test/Android.bp
+++ b/services/vibratorservice/test/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_haptics_framework",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "frameworks_native_license"