Merge "Removing `device_id_attestation` from exclude feature list of AOSP targets." into main
diff --git a/TEST_MAPPING b/TEST_MAPPING
index cd8f3cd..9c01169 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -7,7 +7,8 @@
           "include-filter": "*"
         },
         {
-          "exclude-filter": "*ChildLayerTest#ChildrenSurviveParentDestruction"
+          // TODO(b/305717998): Deflake and re-enable
+          "exclude-filter": "*ChildLayerTest*"
         }
       ]
     },
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 6c2b313..620c23c 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -118,7 +118,8 @@
     ],
 
     srcs: [
-        "OS.cpp",
+        "OS_android.cpp",
+        "OS_unix_base.cpp",
         "RpcTransportRaw.cpp",
     ],
 
@@ -249,6 +250,7 @@
 
     srcs: [
         // Trusty-specific files
+        "OS_android.cpp",
         "trusty/logging.cpp",
         "trusty/OS.cpp",
         "trusty/RpcServerTrusty.cpp",
@@ -357,6 +359,38 @@
 }
 
 cc_library_static {
+    name: "libbinder_rpc_no_blob",
+    vendor_available: true,
+    defaults: [
+        "libbinder_common_defaults",
+        "libbinder_android_defaults",
+        "libbinder_kernel_defaults",
+    ],
+    cflags: [
+        "-DBINDER_DISABLE_BLOB",
+    ],
+    visibility: [
+        ":__subpackages__",
+    ],
+}
+
+cc_library_static {
+    name: "libbinder_rpc_no_native_handle",
+    vendor_available: true,
+    defaults: [
+        "libbinder_common_defaults",
+        "libbinder_android_defaults",
+        "libbinder_kernel_defaults",
+    ],
+    cflags: [
+        "-DBINDER_DISABLE_NATIVE_HANDLE",
+    ],
+    visibility: [
+        ":__subpackages__",
+    ],
+}
+
+cc_library_static {
     name: "libbinder_rpc_single_threaded",
     defaults: [
         "libbinder_common_defaults",
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 9f091ef..f22e90a 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -40,6 +40,7 @@
 #endif
 
 #include "BuildFlags.h"
+#include "OS.h"
 #include "RpcState.h"
 
 namespace android {
@@ -795,7 +796,7 @@
         }
 
         case SYSPROPS_TRANSACTION: {
-            report_sysprop_change();
+            if (!binder::os::report_sysprop_change()) return INVALID_OPERATION;
             return NO_ERROR;
         }
 
diff --git a/libs/binder/OS.h b/libs/binder/OS.h
index fecae31..8dc1f6a 100644
--- a/libs/binder/OS.h
+++ b/libs/binder/OS.h
@@ -23,7 +23,7 @@
 #include <binder/RpcTransport.h>
 #include <utils/Errors.h>
 
-namespace android {
+namespace android::binder::os {
 
 android::base::Result<void> setNonBlocking(android::base::borrowed_fd fd);
 
@@ -41,4 +41,8 @@
         const RpcTransportFd& socket, iovec* iovs, int niovs,
         std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds);
 
-} // namespace android
+uint64_t GetThreadId();
+
+bool report_sysprop_change();
+
+} // namespace android::binder::os
diff --git a/libs/binder/OS_android.cpp b/libs/binder/OS_android.cpp
new file mode 100644
index 0000000..ad458eb
--- /dev/null
+++ b/libs/binder/OS_android.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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 "OS.h"
+
+#include <android-base/threads.h>
+#include <utils/misc.h>
+
+namespace android::binder::os {
+
+uint64_t GetThreadId() {
+#ifdef BINDER_RPC_SINGLE_THREADED
+    return 0;
+#else
+    return base::GetThreadId();
+#endif
+}
+
+bool report_sysprop_change() {
+    android::report_sysprop_change();
+    return true;
+}
+
+} // namespace android::binder::os
diff --git a/libs/binder/OS.cpp b/libs/binder/OS_unix_base.cpp
similarity index 98%
rename from libs/binder/OS.cpp
rename to libs/binder/OS_unix_base.cpp
index ce60e33..81933d5 100644
--- a/libs/binder/OS.cpp
+++ b/libs/binder/OS_unix_base.cpp
@@ -24,7 +24,7 @@
 using android::base::ErrnoError;
 using android::base::Result;
 
-namespace android {
+namespace android::binder::os {
 
 // Linux kernel supports up to 253 (from SCM_MAX_FD) for unix sockets.
 constexpr size_t kMaxFdsPerMsg = 253;
@@ -162,4 +162,4 @@
     return TEMP_FAILURE_RETRY(recvmsg(socket.fd.get(), &msg, MSG_NOSIGNAL));
 }
 
-} // namespace android
+} // namespace android::binder::os
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index d92de1b..17bdc45 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -40,7 +40,9 @@
 #include <binder/TextOutput.h>
 
 #include <android-base/scopeguard.h>
+#ifndef BINDER_DISABLE_BLOB
 #include <cutils/ashmem.h>
+#endif
 #include <utils/Flattenable.h>
 #include <utils/Log.h>
 #include <utils/String16.h>
@@ -621,7 +623,7 @@
                 // To match kernel binder behavior, we always dup, even if the
                 // FD was unowned in the source parcel.
                 int newFd = -1;
-                if (status_t status = dupFileDescriptor(oldFd, &newFd); status != OK) {
+                if (status_t status = binder::os::dupFileDescriptor(oldFd, &newFd); status != OK) {
                     ALOGW("Failed to duplicate file descriptor %d: %s", oldFd, strerror(-status));
                 }
                 rpcFields->mFds->emplace_back(base::unique_fd(newFd));
@@ -1434,6 +1436,7 @@
     return writeParcelable(*parcelable);
 }
 
+#ifndef BINDER_DISABLE_NATIVE_HANDLE
 status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
     if (!handle || handle->version != sizeof(native_handle))
@@ -1456,6 +1459,7 @@
     err = write(handle->data + handle->numFds, sizeof(int)*handle->numInts);
     return err;
 }
+#endif
 
 status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership) {
     if (auto* rpcFields = maybeRpcFields()) {
@@ -1513,7 +1517,7 @@
 status_t Parcel::writeDupFileDescriptor(int fd)
 {
     int dupFd;
-    if (status_t err = dupFileDescriptor(fd, &dupFd); err != OK) {
+    if (status_t err = binder::os::dupFileDescriptor(fd, &dupFd); err != OK) {
         return err;
     }
     status_t err = writeFileDescriptor(dupFd, true /*takeOwnership*/);
@@ -1532,7 +1536,7 @@
 status_t Parcel::writeDupParcelFileDescriptor(int fd)
 {
     int dupFd;
-    if (status_t err = dupFileDescriptor(fd, &dupFd); err != OK) {
+    if (status_t err = binder::os::dupFileDescriptor(fd, &dupFd); err != OK) {
         return err;
     }
     status_t err = writeParcelFileDescriptor(dupFd, true /*takeOwnership*/);
@@ -1548,6 +1552,12 @@
 
 status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob)
 {
+#ifdef BINDER_DISABLE_BLOB
+    (void)len;
+    (void)mutableCopy;
+    (void)outBlob;
+    return INVALID_OPERATION;
+#else
     if (len > INT32_MAX) {
         // don't accept size_t values which may have come from an
         // inadvertent conversion from a negative int.
@@ -1599,6 +1609,7 @@
     }
     ::close(fd);
     return status;
+#endif
 }
 
 status_t Parcel::writeDupImmutableBlobFileDescriptor(int fd)
@@ -2230,6 +2241,7 @@
     return status.exceptionCode();
 }
 
+#ifndef BINDER_DISABLE_NATIVE_HANDLE
 native_handle* Parcel::readNativeHandle() const
 {
     int numFds, numInts;
@@ -2262,6 +2274,7 @@
     }
     return h;
 }
+#endif
 
 int Parcel::readFileDescriptor() const {
     if (const auto* rpcFields = maybeRpcFields()) {
@@ -2345,7 +2358,7 @@
     }
 
     int dupFd;
-    if (status_t err = dupFileDescriptor(got, &dupFd); err != OK) {
+    if (status_t err = binder::os::dupFileDescriptor(got, &dupFd); err != OK) {
         return BAD_VALUE;
     }
 
@@ -2367,7 +2380,7 @@
     }
 
     int dupFd;
-    if (status_t err = dupFileDescriptor(got, &dupFd); err != OK) {
+    if (status_t err = binder::os::dupFileDescriptor(got, &dupFd); err != OK) {
         return BAD_VALUE;
     }
 
@@ -2382,6 +2395,11 @@
 
 status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
 {
+#ifdef BINDER_DISABLE_BLOB
+    (void)len;
+    (void)outBlob;
+    return INVALID_OPERATION;
+#else
     int32_t blobType;
     status_t status = readInt32(&blobType);
     if (status) return status;
@@ -2415,6 +2433,7 @@
 
     outBlob->init(fd, ptr, len, isMutable);
     return NO_ERROR;
+#endif
 }
 
 status_t Parcel::read(FlattenableHelperInterface& val) const
@@ -3158,6 +3177,7 @@
     }
 
     size_t openAshmemSize = 0;
+#ifndef BINDER_DISABLE_BLOB
     for (size_t i = 0; i < kernelFields->mObjectsSize; i++) {
         const flat_binder_object* flat =
                 reinterpret_cast<const flat_binder_object*>(mData + kernelFields->mObjects[i]);
@@ -3172,6 +3192,7 @@
             }
         }
     }
+#endif
     return openAshmemSize;
 }
 #endif // BINDER_WITH_KERNEL_IPC
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 55fc16d..07ab093 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "RpcServer"
 
 #include <inttypes.h>
+#include <netinet/tcp.h>
 #include <poll.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -24,7 +25,6 @@
 #include <thread>
 #include <vector>
 
-#include <android-base/hex.h>
 #include <android-base/scopeguard.h>
 #include <binder/Parcel.h>
 #include <binder/RpcServer.h>
@@ -57,7 +57,7 @@
 sp<RpcServer> RpcServer::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) {
     // Default is without TLS.
     if (rpcTransportCtxFactory == nullptr)
-        rpcTransportCtxFactory = makeDefaultRpcTransportCtxFactory();
+        rpcTransportCtxFactory = binder::os::makeDefaultRpcTransportCtxFactory();
     auto ctx = rpcTransportCtxFactory->newServerCtx();
     if (ctx == nullptr) return nullptr;
     return sp<RpcServer>::make(std::move(ctx));
@@ -216,7 +216,7 @@
     iovec iov{&zero, sizeof(zero)};
     std::vector<std::variant<base::unique_fd, base::borrowed_fd>> fds;
 
-    ssize_t num_bytes = receiveMessageFromSocket(server.mServer, &iov, 1, &fds);
+    ssize_t num_bytes = binder::os::receiveMessageFromSocket(server.mServer, &iov, 1, &fds);
     if (num_bytes < 0) {
         int savedErrno = errno;
         ALOGE("Failed recvmsg: %s", strerror(savedErrno));
@@ -231,7 +231,7 @@
     }
 
     unique_fd fd(std::move(std::get<unique_fd>(fds.back())));
-    if (auto res = setNonBlocking(fd); !res.ok()) {
+    if (auto res = binder::os::setNonBlocking(fd); !res.ok()) {
         ALOGE("Failed setNonBlocking: %s", res.error().message().c_str());
         return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code();
     }
@@ -484,11 +484,11 @@
                 // don't block if there is some entropy issue
                 if (tries++ > 5) {
                     ALOGE("Cannot find new address: %s",
-                          base::HexString(sessionId.data(), sessionId.size()).c_str());
+                          HexString(sessionId.data(), sessionId.size()).c_str());
                     return;
                 }
 
-                auto status = getRandomBytes(sessionId.data(), sessionId.size());
+                auto status = binder::os::getRandomBytes(sessionId.data(), sessionId.size());
                 if (status != OK) {
                     ALOGE("Failed to read random session ID: %s", strerror(-status));
                     return;
@@ -536,7 +536,7 @@
             auto it = server->mSessions.find(sessionId);
             if (it == server->mSessions.end()) {
                 ALOGE("Cannot add thread, no record of session with ID %s",
-                      base::HexString(sessionId.data(), sessionId.size()).c_str());
+                      HexString(sessionId.data(), sessionId.size()).c_str());
                 return;
             }
             session = it->second;
@@ -572,6 +572,17 @@
         return -savedErrno;
     }
 
+    if (addr.addr()->sa_family == AF_INET || addr.addr()->sa_family == AF_INET6) {
+        int noDelay = 1;
+        int result =
+                setsockopt(socket_fd.get(), IPPROTO_TCP, TCP_NODELAY, &noDelay, sizeof(noDelay));
+        if (result < 0) {
+            int savedErrno = errno;
+            ALOGE("Could not set TCP_NODELAY on  %s", strerror(savedErrno));
+            return -savedErrno;
+        }
+    }
+
     {
         RpcMutexLockGuard _l(mLock);
         if (mServerSocketModifier != nullptr) {
@@ -610,15 +621,14 @@
 void RpcServer::onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) {
     const std::vector<uint8_t>& id = session->mId;
     LOG_ALWAYS_FATAL_IF(id.empty(), "Server sessions must be initialized with ID");
-    LOG_RPC_DETAIL("Dropping session with address %s",
-                   base::HexString(id.data(), id.size()).c_str());
+    LOG_RPC_DETAIL("Dropping session with address %s", HexString(id.data(), id.size()).c_str());
 
     RpcMutexLockGuard _l(mLock);
     auto it = mSessions.find(id);
     LOG_ALWAYS_FATAL_IF(it == mSessions.end(), "Bad state, unknown session id %s",
-                        base::HexString(id.data(), id.size()).c_str());
+                        HexString(id.data(), id.size()).c_str());
     LOG_ALWAYS_FATAL_IF(it->second != session, "Bad state, session has id mismatch %s",
-                        base::HexString(id.data(), id.size()).c_str());
+                        HexString(id.data(), id.size()).c_str());
     (void)mSessions.erase(it);
 }
 
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index c3dee16..fa8f2b5 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -26,7 +26,6 @@
 
 #include <string_view>
 
-#include <android-base/hex.h>
 #include <android-base/macros.h>
 #include <android-base/scopeguard.h>
 #include <binder/BpBinder.h>
@@ -70,7 +69,7 @@
 
 sp<RpcSession> RpcSession::make() {
     // Default is without TLS.
-    return make(makeDefaultRpcTransportCtxFactory());
+    return make(binder::os::makeDefaultRpcTransportCtxFactory());
 }
 
 sp<RpcSession> RpcSession::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) {
@@ -195,7 +194,7 @@
             fd = request();
             if (!fd.ok()) return BAD_VALUE;
         }
-        if (auto res = setNonBlocking(fd); !res.ok()) {
+        if (auto res = binder::os::setNonBlocking(fd); !res.ok()) {
             ALOGE("setupPreconnectedClient: %s", res.error().message().c_str());
             return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code();
         }
@@ -310,8 +309,7 @@
     status = state()->getSessionId(connection.get(), sp<RpcSession>::fromExisting(this), &mId);
     if (status != OK) return status;
 
-    LOG_RPC_DETAIL("RpcSession %p has id %s", this,
-                   base::HexString(mId.data(), mId.size()).c_str());
+    LOG_RPC_DETAIL("RpcSession %p has id %s", this, HexString(mId.data(), mId.size()).c_str());
     return OK;
 }
 
@@ -709,7 +707,7 @@
                                                 std::nullopt, nullptr);
         if (sendSessionIdStatus != OK) {
             ALOGE("Could not write session ID ('%s') to socket: %s",
-                  base::HexString(sessionId.data(), sessionId.size()).c_str(),
+                  HexString(sessionId.data(), sessionId.size()).c_str(),
                   statusToString(sendSessionIdStatus).c_str());
             return sendSessionIdStatus;
         }
@@ -770,7 +768,7 @@
     {
         RpcMutexLockGuard _l(mMutex);
         connection->rpcTransport = std::move(rpcTransport);
-        connection->exclusiveTid = rpcGetThreadId();
+        connection->exclusiveTid = binder::os::GetThreadId();
         mConnections.mOutgoing.push_back(connection);
     }
 
@@ -825,7 +823,7 @@
 
     sp<RpcConnection> session = sp<RpcConnection>::make();
     session->rpcTransport = std::move(rpcTransport);
-    session->exclusiveTid = rpcGetThreadId();
+    session->exclusiveTid = binder::os::GetThreadId();
 
     mConnections.mIncoming.push_back(session);
     mConnections.mMaxIncoming = mConnections.mIncoming.size();
@@ -870,7 +868,7 @@
     connection->mConnection = nullptr;
     connection->mReentrant = false;
 
-    uint64_t tid = rpcGetThreadId();
+    uint64_t tid = binder::os::GetThreadId();
     RpcMutexUniqueLock _l(session->mMutex);
 
     session->mConnections.mWaitingThreads++;
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index bac2808..5046253 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -18,7 +18,6 @@
 
 #include "RpcState.h"
 
-#include <android-base/hex.h>
 #include <android-base/macros.h>
 #include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
@@ -363,7 +362,7 @@
     for (int i = 0; i < niovs; i++) {
         LOG_RPC_DETAIL("Sending %s (part %d of %d) on RpcTransport %p: %s",
                        what, i + 1, niovs, connection->rpcTransport.get(),
-                       android::base::HexString(iovs[i].iov_base, iovs[i].iov_len).c_str());
+                       HexString(iovs[i].iov_base, iovs[i].iov_len).c_str());
     }
 
     if (status_t status =
@@ -398,7 +397,7 @@
     for (int i = 0; i < niovs; i++) {
         LOG_RPC_DETAIL("Received %s (part %d of %d) on RpcTransport %p: %s",
                        what, i + 1, niovs, connection->rpcTransport.get(),
-                       android::base::HexString(iovs[i].iov_base, iovs[i].iov_len).c_str());
+                       HexString(iovs[i].iov_base, iovs[i].iov_len).c_str());
     }
     return OK;
 }
@@ -409,10 +408,11 @@
         char codename[PROPERTY_VALUE_MAX];
         property_get("ro.build.version.codename", codename, "");
         if (!strcmp(codename, "REL")) {
-            ALOGE("Cannot use experimental RPC binder protocol on a release branch.");
+            ALOGE("Cannot use experimental RPC binder protocol in a release configuration.");
             return false;
         }
 #else
+        // TODO(b/305983144)
         // don't restrict on other platforms, though experimental should
         // only really be used for testing, we don't have a good way to see
         // what is shipping outside of Android
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index ddbcb57..c089811 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -59,8 +59,8 @@
             override {
         bool sentFds = false;
         auto send = [&](iovec* iovs, int niovs) -> ssize_t {
-            ssize_t ret =
-                    sendMessageOnSocket(mSocket, iovs, niovs, sentFds ? nullptr : ancillaryFds);
+            ssize_t ret = binder::os::sendMessageOnSocket(mSocket, iovs, niovs,
+                                                          sentFds ? nullptr : ancillaryFds);
             sentFds |= ret > 0;
             return ret;
         };
@@ -73,7 +73,7 @@
             const std::optional<android::base::function_ref<status_t()>>& altPoll,
             std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override {
         auto recv = [&](iovec* iovs, int niovs) -> ssize_t {
-            return receiveMessageFromSocket(mSocket, iovs, niovs, ancillaryFds);
+            return binder::os::receiveMessageFromSocket(mSocket, iovs, niovs, ancillaryFds);
         };
         return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN,
                                         altPoll);
diff --git a/libs/binder/Utils.cpp b/libs/binder/Utils.cpp
index 0314b0f..47fd17d 100644
--- a/libs/binder/Utils.cpp
+++ b/libs/binder/Utils.cpp
@@ -16,6 +16,7 @@
 
 #include "Utils.h"
 
+#include <android-base/logging.h>
 #include <string.h>
 
 namespace android {
@@ -24,4 +25,22 @@
     memset(data, 0, size);
 }
 
+std::string HexString(const void* bytes, size_t len) {
+    CHECK(bytes != nullptr || len == 0) << bytes << " " << len;
+
+    // b/132916539: Doing this the 'C way', std::setfill triggers ubsan implicit conversion
+    const uint8_t* bytes8 = static_cast<const uint8_t*>(bytes);
+    const char chars[] = "0123456789abcdef";
+    std::string result;
+    result.resize(len * 2);
+
+    for (size_t i = 0; i < len; i++) {
+        const auto c = bytes8[i];
+        result[2 * i] = chars[c >> 4];
+        result[2 * i + 1] = chars[c & 0xf];
+    }
+
+    return result;
+}
+
 } // namespace android
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
index e04199c..dd632c0 100644
--- a/libs/binder/Utils.h
+++ b/libs/binder/Utils.h
@@ -70,4 +70,10 @@
     }
 };
 
+// Converts binary data into a hexString.
+//
+// Hex values are printed in order, e.g. 0xDEAD will result in 'adde' because
+// Android is little-endian.
+std::string HexString(const void* bytes, size_t len);
+
 }   // namespace android
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 45e5ace..98d12bb 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -26,7 +26,9 @@
 #include <vector>
 
 #include <android-base/unique_fd.h>
+#ifndef BINDER_DISABLE_NATIVE_HANDLE
 #include <cutils/native_handle.h>
+#endif
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/String16.h>
@@ -324,11 +326,13 @@
     template<typename T>
     status_t            writeVectorSize(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
 
+#ifndef BINDER_DISABLE_NATIVE_HANDLE
     // Place a native_handle into the parcel (the native_handle's file-
     // descriptors are dup'ed, so it is safe to delete the native_handle
     // when this function returns).
     // Doesn't take ownership of the native_handle.
     status_t            writeNativeHandle(const native_handle* handle);
+#endif
 
     // Place a file descriptor into the parcel.  The given fd must remain
     // valid for the lifetime of the parcel.
@@ -559,13 +563,14 @@
     // response headers rather than doing it by hand.
     int32_t             readExceptionCode() const;
 
+#ifndef BINDER_DISABLE_NATIVE_HANDLE
     // Retrieve native_handle from the parcel. This returns a copy of the
     // parcel's native_handle (the caller takes ownership). The caller
-    // must free the native_handle with native_handle_close() and 
+    // must free the native_handle with native_handle_close() and
     // native_handle_delete().
     native_handle*     readNativeHandle() const;
+#endif
 
-    
     // Retrieve a file descriptor from the parcel.  This returns the raw fd
     // in the parcel, which you do not own -- use dup() to get your own copy.
     int                 readFileDescriptor() const;
@@ -1289,6 +1294,7 @@
 
     // Fields only needed when parcelling for "kernel Binder".
     struct KernelFields {
+        KernelFields() {}
         binder_size_t* mObjects = nullptr;
         size_t mObjectsSize = 0;
         size_t mObjectsCapacity = 0;
diff --git a/libs/binder/include/binder/RpcThreads.h b/libs/binder/include/binder/RpcThreads.h
index b80d116..d25f292 100644
--- a/libs/binder/include/binder/RpcThreads.h
+++ b/libs/binder/include/binder/RpcThreads.h
@@ -17,8 +17,6 @@
 
 #include <pthread.h>
 
-#include <android-base/threads.h>
-
 #include <condition_variable>
 #include <functional>
 #include <memory>
@@ -121,10 +119,6 @@
 }
 } // namespace rpc_this_thread
 
-static inline uint64_t rpcGetThreadId() {
-    return 0;
-}
-
 static inline void rpcJoinIfSingleThreaded(RpcMaybeThread& t) {
     t.join();
 }
@@ -136,10 +130,6 @@
 using RpcMaybeThread = std::thread;
 namespace rpc_this_thread = std::this_thread;
 
-static inline uint64_t rpcGetThreadId() {
-    return base::GetThreadId();
-}
-
 static inline void rpcJoinIfSingleThreaded(RpcMaybeThread&) {}
 #endif // BINDER_RPC_SINGLE_THREADED
 
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 463c210..a08cb7a 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -436,7 +436,7 @@
 
 impl<I: FromIBinder + ?Sized> PartialOrd for Strong<I> {
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        self.0.as_binder().partial_cmp(&other.0.as_binder())
+        Some(self.cmp(other))
     }
 }
 
@@ -483,7 +483,7 @@
 
 impl<I: FromIBinder + ?Sized> PartialOrd for Weak<I> {
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        self.weak_binder.partial_cmp(&other.weak_binder)
+        Some(self.cmp(other))
     }
 }
 
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 8841fe6..ed870b6 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -144,6 +144,7 @@
 #[doc(hidden)]
 pub mod unstable_api {
     pub use crate::binder::AsNative;
+    pub use crate::error::status_result;
     pub use crate::proxy::unstable_api::new_spibinder;
     pub use crate::sys::AIBinder;
     pub use crate::sys::AParcel;
diff --git a/libs/binder/tests/binderClearBufTest.cpp b/libs/binder/tests/binderClearBufTest.cpp
index 3ea5b55..e43ee5f 100644
--- a/libs/binder/tests/binderClearBufTest.cpp
+++ b/libs/binder/tests/binderClearBufTest.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <android-base/hex.h>
 #include <android-base/logging.h>
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
@@ -24,6 +23,8 @@
 #include <binder/Stability.h>
 #include <gtest/gtest.h>
 
+#include "../Utils.h"
+
 #include <sys/prctl.h>
 #include <thread>
 
@@ -68,7 +69,7 @@
             lastReply = reply.data();
             lastReplySize = reply.dataSize();
         }
-        *outBuffer = android::base::HexString(lastReply, lastReplySize);
+        *outBuffer = android::HexString(lastReply, lastReplySize);
         return result;
     }
 };
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 4c3c68e..5884dbe 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -227,7 +227,7 @@
     std::vector<std::variant<base::unique_fd, base::borrowed_fd>> fds;
     fds.emplace_back(std::move(sockServer));
 
-    if (sendMessageOnSocket(transportFd, &iov, 1, &fds) < 0) {
+    if (binder::os::sendMessageOnSocket(transportFd, &iov, 1, &fds) < 0) {
         int savedErrno = errno;
         LOG(FATAL) << "Failed sendMessageOnSocket: " << strerror(savedErrno);
     }
@@ -1589,7 +1589,7 @@
             int buf;
             iovec iov{&buf, sizeof(buf)};
 
-            if (receiveMessageFromSocket(mFd, &iov, 1, &fds) < 0) {
+            if (binder::os::receiveMessageFromSocket(mFd, &iov, 1, &fds) < 0) {
                 int savedErrno = errno;
                 LOG(FATAL) << "Failed receiveMessage: " << strerror(savedErrno);
             }
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index c1364dd..eceff35 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -70,12 +70,23 @@
     return {RpcSecurity::RAW, RpcSecurity::TLS};
 }
 
+static inline bool hasExperimentalRpc() {
+#ifdef __ANDROID__
+    return base::GetProperty("ro.build.version.codename", "") != "REL";
+#else
+    // TODO(b/305983144): restrict on other platforms
+    return true;
+#endif
+}
+
 static inline std::vector<uint32_t> testVersions() {
     std::vector<uint32_t> versions;
     for (size_t i = 0; i < RPC_WIRE_PROTOCOL_VERSION_NEXT; i++) {
         versions.push_back(i);
     }
-    versions.push_back(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
+    if (hasExperimentalRpc()) {
+        versions.push_back(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
+    }
     return versions;
 }
 
diff --git a/libs/binder/tests/binderRpcUniversalTests.cpp b/libs/binder/tests/binderRpcUniversalTests.cpp
index e43508e..885bb45 100644
--- a/libs/binder/tests/binderRpcUniversalTests.cpp
+++ b/libs/binder/tests/binderRpcUniversalTests.cpp
@@ -50,7 +50,8 @@
 
 TEST(BinderRpc, CanUseExperimentalWireVersion) {
     auto session = RpcSession::make();
-    EXPECT_TRUE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL));
+    EXPECT_EQ(hasExperimentalRpc(),
+              session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL));
 }
 
 TEST_P(BinderRpc, Ping) {
diff --git a/libs/binder/tests/binderRpcWireProtocolTest.cpp b/libs/binder/tests/binderRpcWireProtocolTest.cpp
index 642cea4..7ec7c99 100644
--- a/libs/binder/tests/binderRpcWireProtocolTest.cpp
+++ b/libs/binder/tests/binderRpcWireProtocolTest.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <android-base/hex.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/properties.h>
@@ -25,6 +24,7 @@
 #include <gtest/gtest.h>
 
 #include "../Debug.h"
+#include "../Utils.h"
 
 namespace android {
 
@@ -176,7 +176,7 @@
         setParcelForRpc(&p, version);
         kFillFuns[i](&p);
 
-        result += base::HexString(p.data(), p.dataSize());
+        result += HexString(p.data(), p.dataSize());
     }
     return result;
 }
@@ -263,16 +263,4 @@
     }
 }
 
-TEST(RpcWire, IfNotExperimentalCodeHasNoExperimentalFeatures) {
-    if (RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL) {
-        GTEST_SKIP() << "Version is experimental, so experimental features are okay.";
-    }
-
-    // if we set the wire protocol version to experimental, none of the code
-    // should introduce a difference (if this fails, it means we have features
-    // which are enabled under experimental mode, but we aren't actually using
-    // or testing them!)
-    checkRepr(kCurrentRepr, RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
-}
-
 } // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 46d387c..416ffad 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -21,14 +21,15 @@
 #include "parcelables/SingleDataParcelable.h"
 #include "util.h"
 
-#include <android-base/hex.h>
 #include <android/os/IServiceManager.h>
 #include <binder/ParcelableHolder.h>
 #include <binder/PersistableBundle.h>
 #include <binder/Status.h>
 
+#include "../../Utils.h"
+
 using ::android::status_t;
-using ::android::base::HexString;
+using ::android::HexString;
 
 enum ByteEnum : int8_t {};
 enum IntEnum : int32_t {};
diff --git a/libs/binder/tests/parcel_fuzzer/hwbinder.cpp b/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
index 438e8ae..cdc8bcc 100644
--- a/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
@@ -18,12 +18,13 @@
 #include "hwbinder.h"
 #include "util.h"
 
-#include <android-base/hex.h>
 #include <android-base/logging.h>
 #include <hwbinder/Parcel.h>
 
+#include "../../Utils.h"
+
 using ::android::status_t;
-using ::android::base::HexString;
+using ::android::HexString;
 
 // TODO: support scatter-gather types
 
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel_seeds/fuzzseeds/random_parcel_seeds.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel_seeds/fuzzseeds/random_parcel_seeds.h
index 5755239..071250d 100644
--- a/libs/binder/tests/parcel_fuzzer/include_random_parcel_seeds/fuzzseeds/random_parcel_seeds.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel_seeds/fuzzseeds/random_parcel_seeds.h
@@ -15,7 +15,6 @@
  */
 
 #include <android-base/file.h>
-#include <android-base/hex.h>
 #include <android-base/logging.h>
 
 #include <binder/Binder.h>
@@ -27,7 +26,6 @@
 #include <vector>
 
 using android::Parcel;
-using android::base::HexString;
 using std::vector;
 
 namespace android {
diff --git a/libs/binder/tests/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp
index bef4ab6..5b1e9ea 100644
--- a/libs/binder/tests/parcel_fuzzer/main.cpp
+++ b/libs/binder/tests/parcel_fuzzer/main.cpp
@@ -22,7 +22,6 @@
 
 #include <iostream>
 
-#include <android-base/hex.h>
 #include <android-base/logging.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_libbinder.h>
@@ -34,10 +33,12 @@
 #include <sys/resource.h>
 #include <sys/time.h>
 
+#include "../../Utils.h"
+
 using android::fillRandomParcel;
 using android::RandomParcelOptions;
 using android::sp;
-using android::base::HexString;
+using android::HexString;
 
 void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider,
                       RandomParcelOptions* options) {
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index 8ec9823..43e06e0 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -28,7 +28,7 @@
 
 using android::base::Result;
 
-namespace android {
+namespace android::binder::os {
 
 Result<void> setNonBlocking(android::base::borrowed_fd /*fd*/) {
     // Trusty IPC syscalls are all non-blocking by default.
@@ -73,4 +73,4 @@
     return -1;
 }
 
-} // namespace android
+} // namespace android::binder::os
diff --git a/libs/binder/trusty/kernel/rules.mk b/libs/binder/trusty/kernel/rules.mk
index ab7a50d..1f05ef7 100644
--- a/libs/binder/trusty/kernel/rules.mk
+++ b/libs/binder/trusty/kernel/rules.mk
@@ -31,28 +31,22 @@
 	$(LIBBINDER_DIR)/FdTrigger.cpp \
 	$(LIBBINDER_DIR)/IInterface.cpp \
 	$(LIBBINDER_DIR)/IResultReceiver.cpp \
+	$(LIBBINDER_DIR)/OS_android.cpp \
 	$(LIBBINDER_DIR)/Parcel.cpp \
 	$(LIBBINDER_DIR)/Stability.cpp \
 	$(LIBBINDER_DIR)/Status.cpp \
 	$(LIBBINDER_DIR)/Utils.cpp \
 	$(LIBBASE_DIR)/hex.cpp \
 	$(LIBBASE_DIR)/stringprintf.cpp \
-	$(LIBUTILS_DIR)/Errors.cpp \
+	$(LIBUTILS_DIR)/binder/Errors.cpp \
+	$(LIBUTILS_DIR)/binder/RefBase.cpp \
+	$(LIBUTILS_DIR)/binder/SharedBuffer.cpp \
+	$(LIBUTILS_DIR)/binder/String16.cpp \
+	$(LIBUTILS_DIR)/binder/String8.cpp \
+	$(LIBUTILS_DIR)/binder/StrongPointer.cpp \
+	$(LIBUTILS_DIR)/binder/Unicode.cpp \
+	$(LIBUTILS_DIR)/binder/VectorImpl.cpp \
 	$(LIBUTILS_DIR)/misc.cpp \
-	$(LIBUTILS_DIR)/RefBase.cpp \
-	$(LIBUTILS_DIR)/StrongPointer.cpp \
-	$(LIBUTILS_DIR)/Unicode.cpp \
-
-# TODO: remove the following when libbinder supports std::string
-# instead of String16 and String8 for Status and descriptors
-MODULE_SRCS += \
-	$(LIBUTILS_DIR)/SharedBuffer.cpp \
-	$(LIBUTILS_DIR)/String16.cpp \
-	$(LIBUTILS_DIR)/String8.cpp \
-
-# TODO: disable dump() transactions to get rid of Vector
-MODULE_SRCS += \
-	$(LIBUTILS_DIR)/VectorImpl.cpp \
 
 MODULE_DEFINES += \
 	LK_DEBUGLEVEL_NO_ALIASES=1 \
diff --git a/libs/binder/trusty/rules.mk b/libs/binder/trusty/rules.mk
index 42db29a..2e56cbd 100644
--- a/libs/binder/trusty/rules.mk
+++ b/libs/binder/trusty/rules.mk
@@ -35,6 +35,7 @@
 	$(LIBBINDER_DIR)/FdTrigger.cpp \
 	$(LIBBINDER_DIR)/IInterface.cpp \
 	$(LIBBINDER_DIR)/IResultReceiver.cpp \
+	$(LIBBINDER_DIR)/OS_android.cpp \
 	$(LIBBINDER_DIR)/Parcel.cpp \
 	$(LIBBINDER_DIR)/ParcelFileDescriptor.cpp \
 	$(LIBBINDER_DIR)/RpcServer.cpp \
@@ -45,22 +46,15 @@
 	$(LIBBINDER_DIR)/Utils.cpp \
 	$(LIBBASE_DIR)/hex.cpp \
 	$(LIBBASE_DIR)/stringprintf.cpp \
-	$(LIBUTILS_DIR)/Errors.cpp \
+	$(LIBUTILS_DIR)/binder/Errors.cpp \
+	$(LIBUTILS_DIR)/binder/RefBase.cpp \
+	$(LIBUTILS_DIR)/binder/SharedBuffer.cpp \
+	$(LIBUTILS_DIR)/binder/String16.cpp \
+	$(LIBUTILS_DIR)/binder/String8.cpp \
+	$(LIBUTILS_DIR)/binder/StrongPointer.cpp \
+	$(LIBUTILS_DIR)/binder/Unicode.cpp \
+	$(LIBUTILS_DIR)/binder/VectorImpl.cpp \
 	$(LIBUTILS_DIR)/misc.cpp \
-	$(LIBUTILS_DIR)/RefBase.cpp \
-	$(LIBUTILS_DIR)/StrongPointer.cpp \
-	$(LIBUTILS_DIR)/Unicode.cpp \
-
-# TODO: remove the following when libbinder supports std::string
-# instead of String16 and String8 for Status and descriptors
-MODULE_SRCS += \
-	$(LIBUTILS_DIR)/SharedBuffer.cpp \
-	$(LIBUTILS_DIR)/String16.cpp \
-	$(LIBUTILS_DIR)/String8.cpp \
-
-# TODO: disable dump() transactions to get rid of Vector
-MODULE_SRCS += \
-	$(LIBUTILS_DIR)/VectorImpl.cpp \
 
 MODULE_EXPORT_INCLUDES += \
 	$(LOCAL_DIR)/include \
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 16315ed..0a54161 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -138,6 +138,16 @@
     return base::Join(soNames, ':');
 }
 
+static sp<IGpuService> getGpuService() {
+    static const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
+    if (!binder) {
+        ALOGE("Failed to get gpu service");
+        return nullptr;
+    }
+
+    return interface_cast<IGpuService>(binder);
+}
+
 /*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
     static GraphicsEnv env;
     return env;
@@ -160,8 +170,12 @@
     return appDebuggable || platformDebuggable;
 }
 
-void GraphicsEnv::setDriverPathAndSphalLibraries(const std::string path,
-                                                 const std::string sphalLibraries) {
+/**
+ * APIs for updatable graphics drivers
+ */
+
+void GraphicsEnv::setDriverPathAndSphalLibraries(const std::string& path,
+                                                 const std::string& sphalLibraries) {
     if (!mDriverPath.empty() || !mSphalLibraries.empty()) {
         ALOGV("ignoring attempt to change driver path from '%s' to '%s' or change sphal libraries "
               "from '%s' to '%s'",
@@ -174,6 +188,108 @@
     mSphalLibraries = sphalLibraries;
 }
 
+// Return true if all the required libraries from vndk and sphal namespace are
+// linked to the driver namespace correctly.
+bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* destNamespace,
+                                            android_namespace_t* vndkNamespace,
+                                            const std::string& sharedSphalLibraries) {
+    const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
+    if (llndkLibraries.empty()) {
+        return false;
+    }
+    if (!android_link_namespaces(destNamespace, nullptr, llndkLibraries.c_str())) {
+        ALOGE("Failed to link default namespace[%s]", dlerror());
+        return false;
+    }
+
+    const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
+    if (vndkspLibraries.empty()) {
+        return false;
+    }
+    if (!android_link_namespaces(destNamespace, vndkNamespace, vndkspLibraries.c_str())) {
+        ALOGE("Failed to link vndk namespace[%s]", dlerror());
+        return false;
+    }
+
+    if (sharedSphalLibraries.empty()) {
+        return true;
+    }
+
+    // Make additional libraries in sphal to be accessible
+    auto sphalNamespace = android_get_exported_namespace("sphal");
+    if (!sphalNamespace) {
+        ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
+              sharedSphalLibraries.c_str());
+        return false;
+    }
+
+    if (!android_link_namespaces(destNamespace, sphalNamespace, sharedSphalLibraries.c_str())) {
+        ALOGE("Failed to link sphal namespace[%s]", dlerror());
+        return false;
+    }
+
+    return true;
+}
+
+android_namespace_t* GraphicsEnv::getDriverNamespace() {
+    std::lock_guard<std::mutex> lock(mNamespaceMutex);
+
+    if (mDriverNamespace) {
+        return mDriverNamespace;
+    }
+
+    if (mDriverPath.empty()) {
+        // For an application process, driver path is empty means this application is not opted in
+        // to use updatable driver. Application process doesn't have the ability to set up
+        // environment variables and hence before `getenv` call will return.
+        // For a process that is not an application process, if it's run from an environment,
+        // for example shell, where environment variables can be set, then it can opt into using
+        // udpatable driver by setting UPDATABLE_GFX_DRIVER to 1. By setting to 1 the developer
+        // driver will be used currently.
+        // TODO(b/159240322) Support the production updatable driver.
+        const char* id = getenv("UPDATABLE_GFX_DRIVER");
+        if (id == nullptr || std::strcmp(id, "1") != 0) {
+            return nullptr;
+        }
+        const sp<IGpuService> gpuService = getGpuService();
+        if (!gpuService) {
+            return nullptr;
+        }
+        mDriverPath = gpuService->getUpdatableDriverPath();
+        if (mDriverPath.empty()) {
+            return nullptr;
+        }
+        mDriverPath.append(UPDATABLE_DRIVER_ABI);
+        ALOGI("Driver path is setup via UPDATABLE_GFX_DRIVER: %s", mDriverPath.c_str());
+    }
+
+    auto vndkNamespace = android_get_exported_namespace("vndk");
+    if (!vndkNamespace) {
+        return nullptr;
+    }
+
+    mDriverNamespace = android_create_namespace("updatable gfx driver",
+                                                mDriverPath.c_str(), // ld_library_path
+                                                mDriverPath.c_str(), // default_library_path
+                                                ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                                nullptr, // permitted_when_isolated_path
+                                                nullptr);
+
+    if (!linkDriverNamespaceLocked(mDriverNamespace, vndkNamespace, mSphalLibraries)) {
+        mDriverNamespace = nullptr;
+    }
+
+    return mDriverNamespace;
+}
+
+std::string GraphicsEnv::getDriverPath() const {
+    return mDriverPath;
+}
+
+/**
+ * APIs for GpuStats
+ */
+
 void GraphicsEnv::hintActivityLaunch() {
     ATRACE_CALL();
 
@@ -328,16 +444,6 @@
                         extensionHashes, numStats);
 }
 
-static sp<IGpuService> getGpuService() {
-    static const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
-    if (!binder) {
-        ALOGE("Failed to get gpu service");
-        return nullptr;
-    }
-
-    return interface_cast<IGpuService>(binder);
-}
-
 bool GraphicsEnv::readyToSendGpuStatsLocked() {
     // Only send stats for processes having at least one activity launched and that process doesn't
     // skip the GraphicsEnvironment setup.
@@ -410,86 +516,121 @@
     return true;
 }
 
-void* GraphicsEnv::loadLibrary(std::string name) {
-    const android_dlextinfo dlextinfo = {
-            .flags = ANDROID_DLEXT_USE_NAMESPACE,
-            .library_namespace = getAngleNamespace(),
-    };
-
-    std::string libName = std::string("lib") + name + "_angle.so";
-
-    void* so = android_dlopen_ext(libName.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
-
-    if (so) {
-        ALOGD("dlopen_ext from APK (%s) success at %p", libName.c_str(), so);
-        return so;
-    } else {
-        ALOGE("dlopen_ext(\"%s\") failed: %s", libName.c_str(), dlerror());
-    }
-
-    return nullptr;
-}
-
-bool GraphicsEnv::shouldUseAngle(std::string appName) {
-    if (appName != mAngleAppName) {
-        // Make sure we are checking the app we were init'ed for
-        ALOGE("App name does not match: expected '%s', got '%s'", mAngleAppName.c_str(),
-              appName.c_str());
-        return false;
-    }
-
-    return shouldUseAngle();
-}
+/**
+ * APIs for ANGLE
+ */
 
 bool GraphicsEnv::shouldUseAngle() {
     // Make sure we are init'ed
-    if (mAngleAppName.empty()) {
-        ALOGV("App name is empty. setAngleInfo() has not been called to enable ANGLE.");
+    if (mPackageName.empty()) {
+        ALOGV("Package name is empty. setAngleInfo() has not been called to enable ANGLE.");
         return false;
     }
 
-    return (mUseAngle == YES) ? true : false;
+    return mShouldUseAngle;
 }
 
-void GraphicsEnv::updateUseAngle() {
-    const char* ANGLE_PREFER_ANGLE = "angle";
-    const char* ANGLE_PREFER_NATIVE = "native";
-
-    mUseAngle = NO;
-    if (mAngleDeveloperOptIn == ANGLE_PREFER_ANGLE) {
-        ALOGV("User set \"Developer Options\" to force the use of ANGLE");
-        mUseAngle = YES;
-    } else if (mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) {
-        ALOGV("User set \"Developer Options\" to force the use of Native");
-    } else {
-        ALOGV("User set invalid \"Developer Options\": '%s'", mAngleDeveloperOptIn.c_str());
-    }
-}
-
-void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName,
-                               const std::string developerOptIn,
+void GraphicsEnv::setAngleInfo(const std::string& path, const bool shouldUseSystemAngle,
+                               const std::string& packageName,
                                const std::vector<std::string> eglFeatures) {
-    if (mUseAngle != UNKNOWN) {
-        // We've already figured out an answer for this app, so just return.
-        ALOGV("Already evaluated the rules file for '%s': use ANGLE = %s", appName.c_str(),
-              (mUseAngle == YES) ? "true" : "false");
+    if (mShouldUseAngle) {
+        // ANGLE is already set up for this application process, even if the application
+        // needs to switch from apk to system or vice versa, the application process must
+        // be killed and relaunch so that the loader can properly load ANGLE again.
+        // The architecture does not support runtime switch between drivers, so just return.
+        ALOGE("ANGLE is already set for %s", packageName.c_str());
         return;
     }
 
     mAngleEglFeatures = std::move(eglFeatures);
-
     ALOGV("setting ANGLE path to '%s'", path.c_str());
-    mAnglePath = path;
-    ALOGV("setting ANGLE app name to '%s'", appName.c_str());
-    mAngleAppName = appName;
-    ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str());
-    mAngleDeveloperOptIn = developerOptIn;
-
-    // Update the current status of whether we should use ANGLE or not
-    updateUseAngle();
+    mAnglePath = std::move(path);
+    ALOGV("setting app package name to '%s'", packageName.c_str());
+    mPackageName = std::move(packageName);
+    mShouldUseAngle = true;
+    mShouldUseSystemAngle = shouldUseSystemAngle;
 }
 
-void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) {
+std::string& GraphicsEnv::getPackageName() {
+    return mPackageName;
+}
+
+const std::vector<std::string>& GraphicsEnv::getAngleEglFeatures() {
+    return mAngleEglFeatures;
+}
+
+android_namespace_t* GraphicsEnv::getAngleNamespace() {
+    std::lock_guard<std::mutex> lock(mNamespaceMutex);
+
+    if (mAngleNamespace) {
+        return mAngleNamespace;
+    }
+
+    if (mAnglePath.empty() && !mShouldUseSystemAngle) {
+        ALOGV("mAnglePath is empty and not using system ANGLE, abort creating ANGLE namespace");
+        return nullptr;
+    }
+
+    // Construct the search paths for system ANGLE.
+    const char* const defaultLibraryPaths =
+#if defined(__LP64__)
+            "/vendor/lib64/egl:/system/lib64/egl";
+#else
+            "/vendor/lib/egl:/system/lib/egl";
+#endif
+
+    // If the application process will run on top of system ANGLE, construct the namespace
+    // with sphal namespace being the parent namespace so that search paths and libraries
+    // are properly inherited.
+    mAngleNamespace =
+            android_create_namespace("ANGLE",
+                                     mShouldUseSystemAngle ? defaultLibraryPaths
+                                                           : mAnglePath.c_str(), // ld_library_path
+                                     mShouldUseSystemAngle
+                                             ? defaultLibraryPaths
+                                             : mAnglePath.c_str(), // default_library_path
+                                     ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED,
+                                     nullptr, // permitted_when_isolated_path
+                                     mShouldUseSystemAngle ? android_get_exported_namespace("sphal")
+                                                           : nullptr); // parent
+
+    ALOGD_IF(!mAngleNamespace, "Could not create ANGLE namespace from default");
+
+    if (!mShouldUseSystemAngle) {
+        return mAngleNamespace;
+    }
+
+    auto vndkNamespace = android_get_exported_namespace("vndk");
+    if (!vndkNamespace) {
+        return nullptr;
+    }
+
+    if (!linkDriverNamespaceLocked(mAngleNamespace, vndkNamespace, "")) {
+        mAngleNamespace = nullptr;
+    }
+
+    return mAngleNamespace;
+}
+
+void GraphicsEnv::nativeToggleAngleAsSystemDriver(bool enabled) {
+    const sp<IGpuService> gpuService = getGpuService();
+    if (!gpuService) {
+        ALOGE("No GPU service");
+        return;
+    }
+    gpuService->toggleAngleAsSystemDriver(enabled);
+}
+
+bool GraphicsEnv::shouldUseSystemAngle() {
+    return mShouldUseSystemAngle;
+}
+
+/**
+ * APIs for debuggable layers
+ */
+
+void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace,
+                                const std::string& layerPaths) {
     if (mLayerPaths.empty()) {
         mLayerPaths = layerPaths;
         mAppNamespace = appNamespace;
@@ -503,14 +644,6 @@
     return mAppNamespace;
 }
 
-std::string& GraphicsEnv::getAngleAppName() {
-    return mAngleAppName;
-}
-
-const std::vector<std::string>& GraphicsEnv::getAngleEglFeatures() {
-    return mAngleEglFeatures;
-}
-
 const std::string& GraphicsEnv::getLayerPaths() {
     return mLayerPaths;
 }
@@ -523,141 +656,12 @@
     return mDebugLayersGLES;
 }
 
-void GraphicsEnv::setDebugLayers(const std::string layers) {
+void GraphicsEnv::setDebugLayers(const std::string& layers) {
     mDebugLayers = layers;
 }
 
-void GraphicsEnv::setDebugLayersGLES(const std::string layers) {
+void GraphicsEnv::setDebugLayersGLES(const std::string& layers) {
     mDebugLayersGLES = layers;
 }
 
-// Return true if all the required libraries from vndk and sphal namespace are
-// linked to the updatable gfx driver namespace correctly.
-bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) {
-    const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
-    if (llndkLibraries.empty()) {
-        return false;
-    }
-    if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
-        ALOGE("Failed to link default namespace[%s]", dlerror());
-        return false;
-    }
-
-    const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
-    if (vndkspLibraries.empty()) {
-        return false;
-    }
-    if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
-        ALOGE("Failed to link vndk namespace[%s]", dlerror());
-        return false;
-    }
-
-    if (mSphalLibraries.empty()) {
-        return true;
-    }
-
-    // Make additional libraries in sphal to be accessible
-    auto sphalNamespace = android_get_exported_namespace("sphal");
-    if (!sphalNamespace) {
-        ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace",
-              mSphalLibraries.c_str());
-        return false;
-    }
-
-    if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) {
-        ALOGE("Failed to link sphal namespace[%s]", dlerror());
-        return false;
-    }
-
-    return true;
-}
-
-android_namespace_t* GraphicsEnv::getDriverNamespace() {
-    std::lock_guard<std::mutex> lock(mNamespaceMutex);
-
-    if (mDriverNamespace) {
-        return mDriverNamespace;
-    }
-
-    if (mDriverPath.empty()) {
-        // For an application process, driver path is empty means this application is not opted in
-        // to use updatable driver. Application process doesn't have the ability to set up
-        // environment variables and hence before `getenv` call will return.
-        // For a process that is not an application process, if it's run from an environment,
-        // for example shell, where environment variables can be set, then it can opt into using
-        // udpatable driver by setting UPDATABLE_GFX_DRIVER to 1. By setting to 1 the developer
-        // driver will be used currently.
-        // TODO(b/159240322) Support the production updatable driver.
-        const char* id = getenv("UPDATABLE_GFX_DRIVER");
-        if (id == nullptr || std::strcmp(id, "1")) {
-            return nullptr;
-        }
-        const sp<IGpuService> gpuService = getGpuService();
-        if (!gpuService) {
-            return nullptr;
-        }
-        mDriverPath = gpuService->getUpdatableDriverPath();
-        if (mDriverPath.empty()) {
-            return nullptr;
-        }
-        mDriverPath.append(UPDATABLE_DRIVER_ABI);
-        ALOGI("Driver path is setup via UPDATABLE_GFX_DRIVER: %s", mDriverPath.c_str());
-    }
-
-    auto vndkNamespace = android_get_exported_namespace("vndk");
-    if (!vndkNamespace) {
-        return nullptr;
-    }
-
-    mDriverNamespace = android_create_namespace("gfx driver",
-                                                mDriverPath.c_str(), // ld_library_path
-                                                mDriverPath.c_str(), // default_library_path
-                                                ANDROID_NAMESPACE_TYPE_ISOLATED,
-                                                nullptr, // permitted_when_isolated_path
-                                                nullptr);
-
-    if (!linkDriverNamespaceLocked(vndkNamespace)) {
-        mDriverNamespace = nullptr;
-    }
-
-    return mDriverNamespace;
-}
-
-std::string GraphicsEnv::getDriverPath() const {
-    return mDriverPath;
-}
-
-android_namespace_t* GraphicsEnv::getAngleNamespace() {
-    std::lock_guard<std::mutex> lock(mNamespaceMutex);
-
-    if (mAngleNamespace) {
-        return mAngleNamespace;
-    }
-
-    if (mAnglePath.empty()) {
-        ALOGV("mAnglePath is empty, not creating ANGLE namespace");
-        return nullptr;
-    }
-
-    mAngleNamespace = android_create_namespace("ANGLE",
-                                               nullptr,            // ld_library_path
-                                               mAnglePath.c_str(), // default_library_path
-                                               ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED,
-                                               nullptr, // permitted_when_isolated_path
-                                               nullptr);
-
-    ALOGD_IF(!mAngleNamespace, "Could not create ANGLE namespace from default");
-
-    return mAngleNamespace;
-}
-
-void GraphicsEnv::nativeToggleAngleAsSystemDriver(bool enabled) {
-    const sp<IGpuService> gpuService = getGpuService();
-    if (!gpuService) {
-        ALOGE("No GPU service");
-        return;
-    }
-    gpuService->toggleAngleAsSystemDriver(enabled);
-}
-
 } // namespace android
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index f9b234a..fbf2902 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -29,6 +29,11 @@
 
 struct NativeLoaderNamespace;
 
+// The GraphicsEnv is a singleton per application process and is used to properly set up the
+// graphics drivers for the application process during application starts. The architecture of
+// the graphics driver loader does not support runtime switch and only supports switch to different
+// graphics drivers when application process launches and hence the only way to switch to different
+// graphics drivers is to completely kill the application process and relaunch the application.
 class GraphicsEnv {
 public:
     static GraphicsEnv& getInstance();
@@ -55,7 +60,7 @@
     // Also set additional required sphal libraries to the linker for loading
     // graphics drivers. The string is a list of libraries separated by ':',
     // which is required by android_link_namespaces.
-    void setDriverPathAndSphalLibraries(const std::string path, const std::string sphalLibraries);
+    void setDriverPathAndSphalLibraries(const std::string& path, const std::string& sphalLibraries);
     // Get the updatable driver namespace.
     android_namespace_t* getDriverNamespace();
     std::string getDriverPath() const;
@@ -96,8 +101,6 @@
     /*
      * Apis for ANGLE
      */
-    // Check if the requested app should use ANGLE.
-    bool shouldUseAngle(std::string appName);
     // Check if this app process should use ANGLE.
     bool shouldUseAngle();
     // Set a search path for loading ANGLE libraries. The path is a list of
@@ -105,83 +108,96 @@
     // (libraries must be stored uncompressed and page aligned); such elements
     // in the search path must have a '!' after the zip filename, e.g.
     //     /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a
-    void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn,
-                      const std::vector<std::string> eglFeatures);
+    void setAngleInfo(const std::string& path, const bool useSystemAngle,
+                      const std::string& packageName, const std::vector<std::string> eglFeatures);
     // Get the ANGLE driver namespace.
     android_namespace_t* getAngleNamespace();
-    // Get the app name for ANGLE debug message.
-    std::string& getAngleAppName();
-
+    // Get the app package name.
+    std::string& getPackageName();
     const std::vector<std::string>& getAngleEglFeatures();
+    // Set the persist.graphics.egl system property value.
+    void nativeToggleAngleAsSystemDriver(bool enabled);
+    bool shouldUseSystemAngle();
 
     /*
      * Apis for debug layer
      */
     // Set additional layer search paths.
-    void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths);
+    void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string& layerPaths);
     // Get the app namespace for loading layers.
     NativeLoaderNamespace* getAppNamespace();
     // Get additional layer search paths.
     const std::string& getLayerPaths();
     // Set the Vulkan debug layers.
-    void setDebugLayers(const std::string layers);
+    void setDebugLayers(const std::string& layers);
     // Set the GL debug layers.
-    void setDebugLayersGLES(const std::string layers);
+    void setDebugLayersGLES(const std::string& layers);
     // Get the debug layers to load.
     const std::string& getDebugLayers();
     // Get the debug layers to load.
     const std::string& getDebugLayersGLES();
-    // Set the persist.graphics.egl system property value.
-    void nativeToggleAngleAsSystemDriver(bool enabled);
 
 private:
-    enum UseAngle { UNKNOWN, YES, NO };
-
-    // Load requested ANGLE library.
-    void* loadLibrary(std::string name);
-    // Update whether ANGLE should be used.
-    void updateUseAngle();
     // Link updatable driver namespace with llndk and vndk-sp libs.
-    bool linkDriverNamespaceLocked(android_namespace_t* vndkNamespace);
+    bool linkDriverNamespaceLocked(android_namespace_t* destNamespace,
+                                   android_namespace_t* vndkNamespace,
+                                   const std::string& sharedSphalLibraries);
     // Check whether this process is ready to send stats.
     bool readyToSendGpuStatsLocked();
     // Send the initial complete GpuStats to GpuService.
     void sendGpuStatsLocked(GpuStatsInfo::Api api, bool isDriverLoaded, int64_t driverLoadingTime);
 
     GraphicsEnv() = default;
+
+    // This mutex protects the namespace creation.
+    std::mutex mNamespaceMutex;
+
+    /**
+     * Updatable driver variables.
+     */
     // Path to updatable driver libs.
     std::string mDriverPath;
     // Path to additional sphal libs linked to updatable driver namespace.
     std::string mSphalLibraries;
+    // Updatable driver namespace.
+    android_namespace_t* mDriverNamespace = nullptr;
+
+    /**
+     * ANGLE variables.
+     */
+    // Path to ANGLE libs.
+    std::string mAnglePath;
+    // App's package name.
+    std::string mPackageName;
+    // ANGLE EGL features;
+    std::vector<std::string> mAngleEglFeatures;
+    // Whether ANGLE should be used.
+    bool mShouldUseAngle = false;
+    // Whether loader should load system ANGLE.
+    bool mShouldUseSystemAngle = false;
+    // ANGLE namespace.
+    android_namespace_t* mAngleNamespace = nullptr;
+
+    /**
+     * GPU metrics.
+     */
     // This mutex protects mGpuStats and get gpuservice call.
     std::mutex mStatsLock;
     // Cache the activity launch info
     bool mActivityLaunched = false;
     // Information bookkept for GpuStats.
     GpuStatsInfo mGpuStats;
-    // Path to ANGLE libs.
-    std::string mAnglePath;
-    // This App's name.
-    std::string mAngleAppName;
-    // ANGLE developer opt in status.
-    std::string mAngleDeveloperOptIn;
-    // ANGLE EGL features;
-    std::vector<std::string> mAngleEglFeatures;
-    // Use ANGLE flag.
-    UseAngle mUseAngle = UNKNOWN;
+
+    /**
+     * Debug layers.
+     */
     // Vulkan debug layers libs.
     std::string mDebugLayers;
     // GL debug layers libs.
     std::string mDebugLayersGLES;
     // Additional debug layers search path.
     std::string mLayerPaths;
-    // This mutex protects the namespace creation.
-    std::mutex mNamespaceMutex;
-    // Updatable driver namespace.
-    android_namespace_t* mDriverNamespace = nullptr;
-    // ANGLE namespace.
-    android_namespace_t* mAngleNamespace = nullptr;
-    // This App's namespace.
+    // This App's namespace to open native libraries.
     NativeLoaderNamespace* mAppNamespace = nullptr;
 };
 
diff --git a/libs/input/MotionPredictor.cpp b/libs/input/MotionPredictor.cpp
index 3037573..abcca34 100644
--- a/libs/input/MotionPredictor.cpp
+++ b/libs/input/MotionPredictor.cpp
@@ -176,12 +176,13 @@
     int64_t predictionTime = mBuffers->lastTimestamp();
     const int64_t futureTime = timestamp + mPredictionTimestampOffsetNanos;
 
-    for (int i = 0; i < predictedR.size() && predictionTime <= futureTime; ++i) {
+    for (size_t i = 0; i < static_cast<size_t>(predictedR.size()) && predictionTime <= futureTime;
+         ++i) {
         const TfLiteMotionPredictorSample::Point point =
                 convertPrediction(axisFrom, axisTo, predictedR[i], predictedPhi[i]);
         // TODO(b/266747654): Stop predictions if confidence is < some threshold.
 
-        ALOGD_IF(isDebug(), "prediction %d: %f, %f", i, point.x, point.y);
+        ALOGD_IF(isDebug(), "prediction %zu: %f, %f", i, point.x, point.y);
         PointerCoords coords;
         coords.clear();
         coords.setAxisValue(AMOTION_EVENT_AXIS_X, point.x);
diff --git a/libs/input/TfLiteMotionPredictor.cpp b/libs/input/TfLiteMotionPredictor.cpp
index 85fa176..8d10ff5 100644
--- a/libs/input/TfLiteMotionPredictor.cpp
+++ b/libs/input/TfLiteMotionPredictor.cpp
@@ -115,8 +115,7 @@
                         tensor->name, TfLiteTypeGetName(tensor->type), TfLiteTypeGetName(type));
 
     LOG_ALWAYS_FATAL_IF(!tensor->data.data);
-    return {reinterpret_cast<T*>(tensor->data.data),
-            static_cast<typename std::span<T>::index_type>(tensor->bytes / sizeof(T))};
+    return std::span<T>(reinterpret_cast<T*>(tensor->data.data), tensor->bytes / sizeof(T));
 }
 
 // Verifies that a tensor exists and has an underlying buffer of type T.
diff --git a/libs/input/tests/TfLiteMotionPredictor_test.cpp b/libs/input/tests/TfLiteMotionPredictor_test.cpp
index b5ed9e4..c3ac0b7 100644
--- a/libs/input/tests/TfLiteMotionPredictor_test.cpp
+++ b/libs/input/tests/TfLiteMotionPredictor_test.cpp
@@ -130,19 +130,19 @@
     std::unique_ptr<TfLiteMotionPredictorModel> model = TfLiteMotionPredictorModel::create();
     ASSERT_GT(model->inputLength(), 0u);
 
-    const int inputLength = model->inputLength();
-    ASSERT_EQ(inputLength, model->inputR().size());
-    ASSERT_EQ(inputLength, model->inputPhi().size());
-    ASSERT_EQ(inputLength, model->inputPressure().size());
-    ASSERT_EQ(inputLength, model->inputOrientation().size());
-    ASSERT_EQ(inputLength, model->inputTilt().size());
+    const size_t inputLength = model->inputLength();
+    ASSERT_EQ(inputLength, static_cast<size_t>(model->inputR().size()));
+    ASSERT_EQ(inputLength, static_cast<size_t>(model->inputPhi().size()));
+    ASSERT_EQ(inputLength, static_cast<size_t>(model->inputPressure().size()));
+    ASSERT_EQ(inputLength, static_cast<size_t>(model->inputOrientation().size()));
+    ASSERT_EQ(inputLength, static_cast<size_t>(model->inputTilt().size()));
 
     ASSERT_TRUE(model->invoke());
 
-    const int outputLength = model->outputLength();
-    ASSERT_EQ(outputLength, model->outputR().size());
-    ASSERT_EQ(outputLength, model->outputPhi().size());
-    ASSERT_EQ(outputLength, model->outputPressure().size());
+    const size_t outputLength = model->outputLength();
+    ASSERT_EQ(outputLength, static_cast<size_t>(model->outputR().size()));
+    ASSERT_EQ(outputLength, static_cast<size_t>(model->outputPhi().size()));
+    ASSERT_EQ(outputLength, static_cast<size_t>(model->outputPressure().size()));
 }
 
 TEST(TfLiteMotionPredictorTest, ModelOutput) {
diff --git a/libs/nativewindow/rust/Android.bp b/libs/nativewindow/rust/Android.bp
index dc1575c..90d0a8e 100644
--- a/libs/nativewindow/rust/Android.bp
+++ b/libs/nativewindow/rust/Android.bp
@@ -19,7 +19,7 @@
 }
 
 rust_bindgen {
-    name: "libnativewindow_bindgen",
+    name: "libnativewindow_bindgen_internal",
     crate_name: "nativewindow_bindgen",
     wrapper_src: "sys/nativewindow_bindings.h",
     source_stem: "bindings",
@@ -28,13 +28,21 @@
         "--bitfield-enum=AHardwareBuffer_UsageFlags",
 
         "--allowlist-file=.*/nativewindow/include/.*\\.h",
+        "--blocklist-type",
+        "AParcel",
+        "--raw-line",
+        "use binder::unstable_api::AParcel;",
 
         "--with-derive-eq",
         "--with-derive-partialeq",
     ],
     shared_libs: [
+        "libbinder_ndk",
         "libnativewindow",
     ],
+    rustlibs: [
+        "libbinder_rs",
+    ],
 
     // Currently necessary for host builds
     // TODO(b/31559095): bionic on host should define this
@@ -44,12 +52,40 @@
         },
     },
     min_sdk_version: "VanillaIceCream",
+    vendor_available: true,
+}
+
+rust_library {
+    name: "libnativewindow_bindgen",
+    crate_name: "nativewindow_bindgen",
+    srcs: [":libnativewindow_bindgen_internal"],
+    shared_libs: [
+        "libbinder_ndk",
+        "libnativewindow",
+    ],
+    rustlibs: [
+        "libbinder_rs",
+    ],
+    lints: "none",
+    clippy_lints: "none",
+    // Currently necessary for host builds
+    // TODO(b/31559095): bionic on host should define this
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    min_sdk_version: "VanillaIceCream",
+    vendor_available: true,
 }
 
 rust_test {
     name: "libnativewindow_bindgen_test",
-    srcs: [":libnativewindow_bindgen"],
+    srcs: [":libnativewindow_bindgen_internal"],
     crate_name: "nativewindow_bindgen_test",
+    rustlibs: [
+        "libbinder_rs",
+    ],
     test_suites: ["general-tests"],
     auto_gen_config: true,
     clippy_lints: "none",
@@ -60,6 +96,7 @@
     name: "libnativewindow_defaults",
     srcs: ["src/lib.rs"],
     rustlibs: [
+        "libbinder_rs",
         "libnativewindow_bindgen",
     ],
 }
@@ -77,6 +114,7 @@
         },
     },
     min_sdk_version: "VanillaIceCream",
+    vendor_available: true,
 }
 
 rust_test {
diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs
index 6eb3bbc..6f86c4a 100644
--- a/libs/nativewindow/rust/src/lib.rs
+++ b/libs/nativewindow/rust/src/lib.rs
@@ -16,13 +16,22 @@
 
 extern crate nativewindow_bindgen as ffi;
 
-pub use ffi::{AHardwareBuffer, AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};
+pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};
 
+use binder::{
+    binder_impl::{
+        BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Serialize,
+        SerializeArray, SerializeOption, NON_NULL_PARCELABLE_FLAG, NULL_PARCELABLE_FLAG,
+    },
+    unstable_api::{status_result, AsNative},
+    StatusCode,
+};
+use ffi::{AHardwareBuffer, AHardwareBuffer_readFromParcel, AHardwareBuffer_writeToParcel};
 use std::fmt::{self, Debug, Formatter};
 use std::mem::ManuallyDrop;
-use std::ptr::{self, NonNull};
+use std::ptr::{self, null_mut, NonNull};
 
-/// Wrapper around an opaque C AHardwareBuffer.
+/// Wrapper around an opaque C `AHardwareBuffer`.
 #[derive(PartialEq, Eq)]
 pub struct HardwareBuffer(NonNull<AHardwareBuffer>);
 
@@ -120,8 +129,11 @@
     /// Available since API level 31.
     pub fn id(&self) -> u64 {
         let mut out_id = 0;
-        // SAFETY: Neither pointers can be null.
-        let status = unsafe { ffi::AHardwareBuffer_getId(self.0.as_ref(), &mut out_id) };
+        // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid
+        // because it must have been allocated by `AHardwareBuffer_allocate`,
+        // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet
+        // released it. The id pointer must be valid because it comes from a reference.
+        let status = unsafe { ffi::AHardwareBuffer_getId(self.0.as_ptr(), &mut out_id) };
         assert_eq!(status, 0, "id() failed for AHardwareBuffer with error code: {status}");
 
         out_id
@@ -176,9 +188,10 @@
 
 impl Drop for HardwareBuffer {
     fn drop(&mut self) {
-        // SAFETY: self.0 will never be null. AHardwareBuffers allocated from within Rust will have
-        // a refcount of one, and there is a safety warning on taking an AHardwareBuffer from a raw
-        // pointer requiring callers to ensure the refcount is managed appropriately.
+        // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid
+        // because it must have been allocated by `AHardwareBuffer_allocate`,
+        // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet
+        // released it.
         unsafe { ffi::AHardwareBuffer_release(self.0.as_ptr()) }
     }
 }
@@ -197,6 +210,82 @@
     }
 }
 
+impl Serialize for HardwareBuffer {
+    fn serialize(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
+        SerializeOption::serialize_option(Some(self), parcel)
+    }
+}
+
+impl SerializeOption for HardwareBuffer {
+    fn serialize_option(
+        this: Option<&Self>,
+        parcel: &mut BorrowedParcel,
+    ) -> Result<(), StatusCode> {
+        if let Some(this) = this {
+            parcel.write(&NON_NULL_PARCELABLE_FLAG)?;
+
+            let status =
+            // SAFETY: The AHardwareBuffer pointer we pass is guaranteed to be non-null and valid
+            // because it must have been allocated by `AHardwareBuffer_allocate`,
+            // `AHardwareBuffer_readFromParcel` or the caller of `from_raw` and we have not yet
+            // released it.
+                unsafe { AHardwareBuffer_writeToParcel(this.0.as_ptr(), parcel.as_native_mut()) };
+            status_result(status)
+        } else {
+            parcel.write(&NULL_PARCELABLE_FLAG)
+        }
+    }
+}
+
+impl Deserialize for HardwareBuffer {
+    type UninitType = Option<Self>;
+
+    fn uninit() -> Option<Self> {
+        None
+    }
+
+    fn from_init(value: Self) -> Option<Self> {
+        Some(value)
+    }
+
+    fn deserialize(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
+        DeserializeOption::deserialize_option(parcel)
+            .transpose()
+            .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
+    }
+}
+
+impl DeserializeOption for HardwareBuffer {
+    fn deserialize_option(parcel: &BorrowedParcel) -> Result<Option<Self>, StatusCode> {
+        let present: i32 = parcel.read()?;
+        match present {
+            NULL_PARCELABLE_FLAG => Ok(None),
+            NON_NULL_PARCELABLE_FLAG => {
+                let mut buffer = null_mut();
+
+                let status =
+                // SAFETY: Both pointers must be valid because they are obtained from references.
+                // `AHardwareBuffer_readFromParcel` doesn't store them or do anything else special
+                // with them. If it returns success then it will have allocated a new
+                // `AHardwareBuffer` and incremented the reference count, so we can use it until we
+                // release it.
+                    unsafe { AHardwareBuffer_readFromParcel(parcel.as_native(), &mut buffer) };
+
+                status_result(status)?;
+
+                Ok(Some(Self(NonNull::new(buffer).expect(
+                    "AHardwareBuffer_readFromParcel returned success but didn't allocate buffer",
+                ))))
+            }
+            _ => Err(StatusCode::BAD_VALUE),
+        }
+    }
+}
+
+impl SerializeArray for HardwareBuffer {}
+
+impl DeserializeArray for HardwareBuffer {}
+
 // SAFETY: The underlying *AHardwareBuffers can be moved between threads.
 unsafe impl Send for HardwareBuffer {}
 
diff --git a/libs/nativewindow/rust/sys/nativewindow_bindings.h b/libs/nativewindow/rust/sys/nativewindow_bindings.h
index e652aee..4525a42 100644
--- a/libs/nativewindow/rust/sys/nativewindow_bindings.h
+++ b/libs/nativewindow/rust/sys/nativewindow_bindings.h
@@ -16,5 +16,6 @@
 
 #include <android/data_space.h>
 #include <android/hardware_buffer.h>
+#include <android/hardware_buffer_aidl.h>
 #include <android/hdr_metadata.h>
 #include <android/native_window.h>
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index bb3b43a..8d0eb59 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -147,16 +147,26 @@
         RO_BOARD_PLATFORM_PROPERTY,
 };
 
+// Check whether the loaded system drivers should be unloaded in order to
+// load ANGLE or the updatable graphics drivers.
+// If ANGLE namespace is set, it means the application is identified to run on top of ANGLE.
+// If updatable graphics driver namespace is set, it means the application is identified to
+// run on top of updatable graphics drivers.
 static bool should_unload_system_driver(egl_connection_t* cnx) {
     // Return false if the system driver has been unloaded once.
     if (cnx->systemDriverUnloaded) {
         return false;
     }
 
-    // Return true if Angle namespace is set.
+    // Return true if ANGLE namespace is set.
     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
     if (ns) {
-        return true;
+        // Unless the default GLES driver is ANGLE and the process should use system ANGLE, since
+        // the intended GLES driver is already loaded.
+        // This should be updated in a later patch that cleans up namespaces
+        if (!(cnx->angleLoaded && android::GraphicsEnv::getInstance().shouldUseSystemAngle())) {
+            return true;
+        }
     }
 
     // Return true if updated driver namespace is set.
@@ -201,17 +211,17 @@
             do_android_unload_sphal_library(hnd->dso[0]);
         }
         cnx->dso = nullptr;
+        cnx->angleLoaded = false;
     }
 
     cnx->systemDriverUnloaded = true;
 }
 
-void* Loader::open(egl_connection_t* cnx)
-{
+void* Loader::open(egl_connection_t* cnx) {
     ATRACE_CALL();
     const nsecs_t openTime = systemTime();
 
-    if (should_unload_system_driver(cnx)) {
+    if (cnx->dso && should_unload_system_driver(cnx)) {
         unload_system_driver(cnx);
     }
 
@@ -220,8 +230,12 @@
         return cnx->dso;
     }
 
-    // Firstly, try to load ANGLE driver.
-    driver_t* hnd = attempt_to_load_angle(cnx);
+    driver_t* hnd = nullptr;
+    // Firstly, try to load ANGLE driver, if ANGLE should be loaded and fail, abort.
+    if (android::GraphicsEnv::getInstance().shouldUseAngle()) {
+        hnd = attempt_to_load_angle(cnx);
+        LOG_ALWAYS_FATAL_IF(!hnd, "Failed to load ANGLE.");
+    }
 
     if (!hnd) {
         // Secondly, try to load from driver apk.
@@ -279,10 +293,10 @@
                                                             false, systemTime() - openTime);
     } else {
         // init_angle_backend will check if loaded driver is ANGLE or not,
-        // will set cnx->useAngle appropriately.
+        // will set cnx->angleLoaded appropriately.
         // Do this here so that we use ANGLE path when driver is ANGLE (e.g. loaded as native),
         // not just loading ANGLE as option.
-        init_angle_backend(hnd->dso[2], cnx);
+        attempt_to_init_angle_backend(hnd->dso[2], cnx);
     }
 
     LOG_ALWAYS_FATAL_IF(!hnd,
@@ -324,7 +338,7 @@
     delete hnd;
     cnx->dso = nullptr;
 
-    cnx->useAngle = false;
+    cnx->angleLoaded = false;
 }
 
 void Loader::init_api(void* dso,
@@ -536,10 +550,6 @@
 Loader::driver_t* Loader::attempt_to_load_angle(egl_connection_t* cnx) {
     ATRACE_CALL();
 
-    if (!android::GraphicsEnv::getInstance().shouldUseAngle()) {
-        return nullptr;
-    }
-
     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
     if (!ns) {
         return nullptr;
@@ -565,14 +575,14 @@
     return hnd;
 }
 
-void Loader::init_angle_backend(void* dso, egl_connection_t* cnx) {
+void Loader::attempt_to_init_angle_backend(void* dso, egl_connection_t* cnx) {
     void* pANGLEGetDisplayPlatform = dlsym(dso, "ANGLEGetDisplayPlatform");
     if (pANGLEGetDisplayPlatform) {
-        ALOGV("ANGLE GLES library in use");
-        cnx->useAngle = true;
+        ALOGV("ANGLE GLES library loaded");
+        cnx->angleLoaded = true;
     } else {
-        ALOGV("Native GLES library in use");
-        cnx->useAngle = false;
+        ALOGV("Native GLES library loaded");
+        cnx->angleLoaded = false;
     }
 }
 
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 81742ab..cadbd46 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -57,7 +57,7 @@
     driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
     void unload_system_driver(egl_connection_t* cnx);
     void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
-    void init_angle_backend(void* dso, egl_connection_t* cnx);
+    void attempt_to_init_angle_backend(void* dso, egl_connection_t* cnx);
 
     static __attribute__((noinline)) void init_api(void* dso, const char* const* api,
                                                    const char* const* ref_api,
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 525fed1..3317347 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -191,7 +191,7 @@
     if (cnx->dso) {
         EGLDisplay dpy = EGL_NO_DISPLAY;
 
-        if (cnx->useAngle) {
+        if (cnx->angleLoaded) {
             EGLint error;
             dpy = getPlatformDisplayAngle(display, cnx, attrib_list, &error);
             if (error != EGL_NONE) {
@@ -324,7 +324,7 @@
 
         // b/269060366 Conditionally enabled EGL_ANDROID_get_frame_timestamps extension if the
         // device's present timestamps are reliable (which may not be the case on emulators).
-        if (cnx->useAngle) {
+        if (cnx->angleLoaded) {
             if (android::base::GetBoolProperty("service.sf.present_timestamp", false)) {
                 mExtensionString.append("EGL_ANDROID_get_frame_timestamps ");
             }
@@ -432,7 +432,7 @@
         egl_connection_t* const cnx = &gEGLImpl;
         if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
             // If we're using ANGLE reset any custom DisplayPlatform
-            if (cnx->useAngle) {
+            if (cnx->angleLoaded) {
                 angle::resetAnglePlatform(disp.dpy);
             }
             if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index efbe613..33a77c4 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -84,7 +84,7 @@
     if (win != nullptr && connected) {
         // NOTE: When using Vulkan backend, the Vulkan runtime makes all the
         // native_window_* calls, so don't do them here.
-        if (!cnx->useAngle) {
+        if (!cnx->angleLoaded) {
             native_window_set_buffers_format(win, 0);
             if (native_window_api_disconnect(win, NATIVE_WINDOW_API_EGL)) {
                 ALOGW("EGLNativeWindowType %p disconnect failed", win);
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index aefa1f0..440eb17 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -685,7 +685,7 @@
 
     // NOTE: When using Vulkan backend, the Vulkan runtime makes all the
     // native_window_* calls, so don't do them here.
-    if (!cnx->useAngle) {
+    if (!cnx->angleLoaded) {
         int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
         if (result < 0) {
             ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
@@ -704,14 +704,14 @@
     std::vector<AttrType> strippedAttribList;
     if (!processAttributes<AttrType>(dp, window, attrib_list, &colorSpace, &strippedAttribList)) {
         ALOGE("error invalid colorspace: %d", colorSpace);
-        if (!cnx->useAngle) {
+        if (!cnx->angleLoaded) {
             native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
         }
         return EGL_NO_SURFACE;
     }
     attrib_list = strippedAttribList.data();
 
-    if (!cnx->useAngle) {
+    if (!cnx->angleLoaded) {
         int err = native_window_set_buffers_format(window, static_cast<int>(format));
         if (err != 0) {
             ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err);
@@ -743,7 +743,7 @@
     }
 
     // EGLSurface creation failed
-    if (!cnx->useAngle) {
+    if (!cnx->angleLoaded) {
         native_window_set_buffers_format(window, 0);
         native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
     }
@@ -1354,7 +1354,7 @@
         }
     }
 
-    if (!s->cnx->useAngle) {
+    if (!s->cnx->angleLoaded) {
         if (!sendSurfaceMetadata(s)) {
             native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
             return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
@@ -1379,7 +1379,7 @@
         androidRect.bottom = y;
         androidRects.push_back(androidRect);
     }
-    if (!s->cnx->useAngle) {
+    if (!s->cnx->angleLoaded) {
         native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(),
                                          androidRects.size());
     }
@@ -1470,7 +1470,7 @@
         int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
         if (err != 0) {
             return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
-        } else if (!s->cnx->useAngle) {
+        } else if (!s->cnx->angleLoaded) {
             return EGL_TRUE;
         } // else if ANGLE, fall through to the call to the driver (i.e. ANGLE) below
     }
@@ -1484,7 +1484,7 @@
         int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
         if (err != 0) {
             return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
-        } else if (!s->cnx->useAngle) {
+        } else if (!s->cnx->angleLoaded) {
             return EGL_TRUE;
         } // else if ANGLE, fall through to the call to the driver (i.e. ANGLE) below
     }
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index fcc11f1..3bd37cb 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -41,7 +41,8 @@
             libEgl(nullptr),
             libGles1(nullptr),
             libGles2(nullptr),
-            systemDriverUnloaded(false) {
+            systemDriverUnloaded(false),
+            angleLoaded(false) {
         const char* const* entries = platform_names;
         EGLFuncPointer* curr = reinterpret_cast<EGLFuncPointer*>(&platform);
         while (*entries) {
@@ -73,7 +74,7 @@
     void* libGles2;
 
     bool systemDriverUnloaded;
-    bool useAngle; // Was ANGLE successfully loaded
+    bool angleLoaded; // Was ANGLE successfully loaded
 };
 
 extern gl_hooks_t gHooks[2];
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f12aab7..7ea547d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -172,7 +172,6 @@
     mDrawingState.barrierProducerId = 0;
     mDrawingState.bufferTransform = 0;
     mDrawingState.transformToDisplayInverse = false;
-    mDrawingState.crop.makeInvalid();
     mDrawingState.acquireFence = sp<Fence>::make(-1);
     mDrawingState.acquireFenceTime = std::make_shared<FenceTime>(mDrawingState.acquireFence);
     mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
index 2b29530..0b2e5a3 100644
--- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
+++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
@@ -118,7 +118,7 @@
         << info.touchableRegionBounds.right << "," << info.touchableRegionBounds.bottom << "}";
 }
 
-struct find_id : std::unary_function<LayerInfo, bool> {
+struct find_id {
     int id;
     find_id(int id) : id(id) {}
     bool operator()(LayerInfo const& m) const { return m.id == id; }
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HdrOutputControlTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HdrOutputControlTest.cpp
index a2c54ac..db6df22 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HdrOutputControlTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HdrOutputControlTest.cpp
@@ -26,8 +26,6 @@
 
 namespace android {
 
-using aidl::android::hardware::graphics::common::HdrConversionCapability;
-using aidl::android::hardware::graphics::common::HdrConversionStrategy;
 using GuiHdrConversionStrategyTag = gui::HdrConversionStrategy::Tag;
 using gui::aidl_utils::statusTFromBinderStatus;
 
@@ -66,17 +64,15 @@
             sf->getHdrOutputConversionSupport(&hdrOutputConversionSupport);
     ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(getSupportStatus));
 
-    std::vector<HdrConversionStrategy> strategies =
-            {HdrConversionStrategy(std::in_place_index<static_cast<size_t>(
-                                           GuiHdrConversionStrategyTag::passthrough)>),
-             HdrConversionStrategy(std::in_place_index<static_cast<size_t>(
-                                           GuiHdrConversionStrategyTag::autoAllowedHdrTypes)>),
-             HdrConversionStrategy(std::in_place_index<static_cast<size_t>(
-                                           GuiHdrConversionStrategyTag::forceHdrConversion)>)};
+    std::vector<gui::HdrConversionStrategy> strategies = {
+            gui::HdrConversionStrategy::make<GuiHdrConversionStrategyTag::passthrough>(),
+            gui::HdrConversionStrategy::make<GuiHdrConversionStrategyTag::autoAllowedHdrTypes>(),
+            gui::HdrConversionStrategy::make<GuiHdrConversionStrategyTag::forceHdrConversion>(),
+    };
     int32_t outPreferredHdrOutputType = 0;
 
-    for (HdrConversionStrategy strategy : strategies) {
-        binder::Status status = sf->setHdrConversionStrategy(&strategy, &outPreferredHdrOutputType);
+    for (const gui::HdrConversionStrategy& strategy : strategies) {
+        binder::Status status = sf->setHdrConversionStrategy(strategy, &outPreferredHdrOutputType);
 
         if (hdrOutputConversionSupport) {
             ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));