Merge "rust: Use NonNull for non null pointers in proxy.rs"
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 99e0f4c..b2da6d5 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -24,7 +24,7 @@
 cc_defaults {
     name: "idlcli-defaults",
     shared_libs: [
-        "android.hardware.vibrator-V1-ndk_platform",
+        "android.hardware.vibrator-V1-ndk",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 2127f57..f53a256 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -235,6 +235,51 @@
     },
 }
 
+cc_defaults {
+    name: "libbinder_tls_shared_deps",
+    shared_libs: [
+        "libbinder",
+        "libcrypto",
+        "liblog",
+        "libssl",
+        "libutils",
+    ],
+}
+
+cc_defaults {
+    name: "libbinder_tls_defaults",
+    defaults: ["libbinder_tls_shared_deps"],
+    host_supported: true,
+
+    header_libs: [
+        "libbinder_headers",
+    ],
+    export_header_lib_headers: [
+        "libbinder_headers",
+    ],
+    export_include_dirs: ["include_tls"],
+    static_libs: [
+        "libbase",
+    ],
+    srcs: [
+        "RpcTransportTls.cpp",
+    ],
+}
+
+cc_library_shared {
+    name: "libbinder_tls",
+    defaults: ["libbinder_tls_defaults"],
+}
+
+// For testing
+cc_library_static {
+    name: "libbinder_tls_static",
+    defaults: ["libbinder_tls_defaults"],
+    visibility: [
+        ":__subpackages__",
+    ],
+}
+
 // AIDL interface between libbinder and framework.jar
 filegroup {
     name: "libbinder_aidl",
@@ -293,6 +338,8 @@
         "//packages/modules/Virtualization/authfs:__subpackages__",
         "//packages/modules/Virtualization/compos:__subpackages__",
         "//packages/modules/Virtualization/microdroid",
+        "//packages/modules/Virtualization/microdroid_manager",
+        "//packages/modules/Virtualization/virtualizationservice",
     ],
 }
 
diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp
index ecf13dc..b197a6a 100644
--- a/libs/binder/FdTrigger.cpp
+++ b/libs/binder/FdTrigger.cpp
@@ -59,4 +59,19 @@
     }
 }
 
+android::base::Result<bool> FdTrigger::isTriggeredPolled() {
+    pollfd pfd{.fd = mRead.get(), .events = 0, .revents = 0};
+    int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, 0));
+    if (ret < 0) {
+        return android::base::ErrnoError() << "FdTrigger::isTriggeredPolled: Error in poll()";
+    }
+    if (ret == 0) {
+        return false;
+    }
+    if (pfd.revents & POLLHUP) {
+        return true;
+    }
+    return android::base::Error() << "FdTrigger::isTriggeredPolled: poll() returns " << pfd.revents;
+}
+
 } // namespace android
diff --git a/libs/binder/FdTrigger.h b/libs/binder/FdTrigger.h
index 984e685..a428417 100644
--- a/libs/binder/FdTrigger.h
+++ b/libs/binder/FdTrigger.h
@@ -16,6 +16,7 @@
 
 #include <memory>
 
+#include <android-base/result.h>
 #include <android-base/unique_fd.h>
 #include <utils/Errors.h>
 
@@ -34,7 +35,7 @@
     void trigger();
 
     /**
-     * Whether this has been triggered.
+     * Check whether this has been triggered by checking the write end.
      */
     bool isTriggered();
 
@@ -49,6 +50,16 @@
      */
     status_t triggerablePoll(base::borrowed_fd fd, int16_t event);
 
+    /**
+     * Check whether this has been triggered by poll()ing the read end.
+     *
+     * Return:
+     *   true - triggered
+     *   false - not triggered
+     *   error - error when polling
+     */
+    android::base::Result<bool> isTriggeredPolled();
+
 private:
     base::unique_fd mWrite;
     base::unique_fd mRead;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 8ef4341..caa00a5 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -409,7 +409,7 @@
         uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
         result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
         if (result == -1) {
-            ALOGD("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
+            ALOGV("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
         }
     } else {
         ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 4c47005..3e9e5a8 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -484,37 +484,39 @@
         }
 
         if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
-            if (errno == ECONNRESET) {
+            int connErrno = errno;
+            if (connErrno == EAGAIN || connErrno == EINPROGRESS) {
+                // For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or
+                // EINPROGRESS (for others). Call poll() and getsockopt() to get the error.
+                status_t pollStatus = mShutdownTrigger->triggerablePoll(serverFd, POLLOUT);
+                if (pollStatus != OK) {
+                    ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
+                          statusToString(pollStatus).c_str());
+                    return pollStatus;
+                }
+                // Set connErrno to the errno that connect() would have set if the fd were blocking.
+                socklen_t connErrnoLen = sizeof(connErrno);
+                int ret =
+                        getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &connErrno, &connErrnoLen);
+                if (ret == -1) {
+                    int savedErrno = errno;
+                    ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s. "
+                          "(Original error from connect() is: %s)",
+                          strerror(savedErrno), strerror(connErrno));
+                    return -savedErrno;
+                }
+                // Retrieved the real connErrno as if connect() was called with a blocking socket
+                // fd. Continue checking connErrno.
+            }
+            if (connErrno == ECONNRESET) {
                 ALOGW("Connection reset on %s", addr.toString().c_str());
                 continue;
             }
-            if (errno != EAGAIN && errno != EINPROGRESS) {
-                int savedErrno = errno;
+            // connErrno could be zero if getsockopt determines so. Hence zero-check again.
+            if (connErrno != 0) {
                 ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
-                      strerror(savedErrno));
-                return -savedErrno;
-            }
-            // For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or
-            // EINPROGRESS (for others). Call poll() and getsockopt() to get the error.
-            status_t pollStatus = mShutdownTrigger->triggerablePoll(serverFd, POLLOUT);
-            if (pollStatus != OK) {
-                ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
-                      statusToString(pollStatus).c_str());
-                return pollStatus;
-            }
-            int soError;
-            socklen_t soErrorLen = sizeof(soError);
-            int ret = getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &soError, &soErrorLen);
-            if (ret == -1) {
-                int savedErrno = errno;
-                ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s",
-                      strerror(savedErrno));
-                return -savedErrno;
-            }
-            if (soError != 0) {
-                ALOGE("After connect(), getsockopt() returns error for socket at %s: %s",
-                      addr.toString().c_str(), strerror(soError));
-                return -soError;
+                      strerror(connErrno));
+                return -connErrno;
             }
         }
         LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index d77fc52..930df12 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -111,7 +111,10 @@
     std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, FdTrigger*) const {
         return std::make_unique<RpcTransportRaw>(std::move(fd));
     }
+    std::string getCertificate(CertificateFormat) const override { return {}; }
+    status_t addTrustedPeerCertificate(CertificateFormat, std::string_view) override { return OK; }
 };
+
 } // namespace
 
 std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryRaw::newServerCtx() const {
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
new file mode 100644
index 0000000..e6cb04e
--- /dev/null
+++ b/libs/binder/RpcTransportTls.cpp
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "RpcTransportTls"
+#include <log/log.h>
+
+#include <poll.h>
+
+#include <openssl/bn.h>
+#include <openssl/ssl.h>
+
+#include <binder/RpcTransportTls.h>
+
+#include "FdTrigger.h"
+#include "RpcState.h"
+
+#define SHOULD_LOG_TLS_DETAIL false
+
+#if SHOULD_LOG_TLS_DETAIL
+#define LOG_TLS_DETAIL(...) ALOGI(__VA_ARGS__)
+#else
+#define LOG_TLS_DETAIL(...) ALOGV(__VA_ARGS__) // for type checking
+#endif
+
+#define TEST_AND_RETURN(value, expr)            \
+    do {                                        \
+        if (!(expr)) {                          \
+            ALOGE("Failed to call: %s", #expr); \
+            return value;                       \
+        }                                       \
+    } while (0)
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+
+namespace android {
+namespace {
+
+constexpr const int kCertValidDays = 30;
+
+// Implement BIO for socket that ignores SIGPIPE.
+int socketNew(BIO* bio) {
+    BIO_set_data(bio, reinterpret_cast<void*>(-1));
+    BIO_set_init(bio, 0);
+    return 1;
+}
+int socketFree(BIO* bio) {
+    LOG_ALWAYS_FATAL_IF(bio == nullptr);
+    return 1;
+}
+int socketRead(BIO* bio, char* buf, int size) {
+    android::base::borrowed_fd fd(static_cast<int>(reinterpret_cast<intptr_t>(BIO_get_data(bio))));
+    int ret = TEMP_FAILURE_RETRY(::recv(fd.get(), buf, size, MSG_NOSIGNAL));
+    BIO_clear_retry_flags(bio);
+    if (errno == EAGAIN || errno == EWOULDBLOCK) {
+        BIO_set_retry_read(bio);
+    }
+    return ret;
+}
+
+int socketWrite(BIO* bio, const char* buf, int size) {
+    android::base::borrowed_fd fd(static_cast<int>(reinterpret_cast<intptr_t>(BIO_get_data(bio))));
+    int ret = TEMP_FAILURE_RETRY(::send(fd.get(), buf, size, MSG_NOSIGNAL));
+    BIO_clear_retry_flags(bio);
+    if (errno == EAGAIN || errno == EWOULDBLOCK) {
+        BIO_set_retry_write(bio);
+    }
+    return ret;
+}
+
+long socketCtrl(BIO* bio, int cmd, long num, void*) { // NOLINT
+    android::base::borrowed_fd fd(static_cast<int>(reinterpret_cast<intptr_t>(BIO_get_data(bio))));
+    if (cmd == BIO_CTRL_FLUSH) return 1;
+    LOG_ALWAYS_FATAL("sockCtrl(fd=%d, %d, %ld)", fd.get(), cmd, num);
+    return 0;
+}
+
+bssl::UniquePtr<BIO> newSocketBio(android::base::borrowed_fd fd) {
+    static const BIO_METHOD* gMethods = ([] {
+        auto methods = BIO_meth_new(BIO_get_new_index(), "socket_no_signal");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_write(methods, socketWrite), "BIO_meth_set_write");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_read(methods, socketRead), "BIO_meth_set_read");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_ctrl(methods, socketCtrl), "BIO_meth_set_ctrl");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_create(methods, socketNew), "BIO_meth_set_create");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_destroy(methods, socketFree), "BIO_meth_set_destroy");
+        return methods;
+    })();
+    bssl::UniquePtr<BIO> ret(BIO_new(gMethods));
+    if (ret == nullptr) return nullptr;
+    BIO_set_data(ret.get(), reinterpret_cast<void*>(fd.get()));
+    BIO_set_init(ret.get(), 1);
+    return ret;
+}
+
+bssl::UniquePtr<EVP_PKEY> makeKeyPairForSelfSignedCert() {
+    bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    if (ec_key == nullptr || !EC_KEY_generate_key(ec_key.get())) {
+        ALOGE("Failed to generate key pair.");
+        return nullptr;
+    }
+    bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
+    // Use set1 instead of assign to avoid leaking ec_key when assign fails. set1 increments
+    // the refcount of the ec_key, so it is okay to release it at the end of this function.
+    if (evp_pkey == nullptr || !EVP_PKEY_set1_EC_KEY(evp_pkey.get(), ec_key.get())) {
+        ALOGE("Failed to assign key pair.");
+        return nullptr;
+    }
+    return evp_pkey;
+}
+
+bssl::UniquePtr<X509> makeSelfSignedCert(EVP_PKEY* evp_pkey, const int valid_days) {
+    bssl::UniquePtr<X509> x509(X509_new());
+    bssl::UniquePtr<BIGNUM> serial(BN_new());
+    bssl::UniquePtr<BIGNUM> serialLimit(BN_new());
+    TEST_AND_RETURN(nullptr, BN_lshift(serialLimit.get(), BN_value_one(), 128));
+    TEST_AND_RETURN(nullptr, BN_rand_range(serial.get(), serialLimit.get()));
+    TEST_AND_RETURN(nullptr, BN_to_ASN1_INTEGER(serial.get(), X509_get_serialNumber(x509.get())));
+    TEST_AND_RETURN(nullptr, X509_gmtime_adj(X509_getm_notBefore(x509.get()), 0));
+    TEST_AND_RETURN(nullptr,
+                    X509_gmtime_adj(X509_getm_notAfter(x509.get()), 60 * 60 * 24 * valid_days));
+
+    X509_NAME* subject = X509_get_subject_name(x509.get());
+    TEST_AND_RETURN(nullptr,
+                    X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC,
+                                               reinterpret_cast<const uint8_t*>("Android"), -1, -1,
+                                               0));
+    TEST_AND_RETURN(nullptr,
+                    X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC,
+                                               reinterpret_cast<const uint8_t*>("BinderRPC"), -1,
+                                               -1, 0));
+    TEST_AND_RETURN(nullptr, X509_set_issuer_name(x509.get(), subject));
+
+    TEST_AND_RETURN(nullptr, X509_set_pubkey(x509.get(), evp_pkey));
+    TEST_AND_RETURN(nullptr, X509_sign(x509.get(), evp_pkey, EVP_sha256()));
+    return x509;
+}
+
+[[maybe_unused]] void sslDebugLog(const SSL* ssl, int type, int value) {
+    switch (type) {
+        case SSL_CB_HANDSHAKE_START:
+            LOG_TLS_DETAIL("Handshake started.");
+            break;
+        case SSL_CB_HANDSHAKE_DONE:
+            LOG_TLS_DETAIL("Handshake done.");
+            break;
+        case SSL_CB_ACCEPT_LOOP:
+            LOG_TLS_DETAIL("Handshake progress: %s", SSL_state_string_long(ssl));
+            break;
+        default:
+            LOG_TLS_DETAIL("SSL Debug Log: type = %d, value = %d", type, value);
+            break;
+    }
+}
+
+// Helper class to ErrorQueue::toString
+class ErrorQueueString {
+public:
+    static std::string toString() {
+        ErrorQueueString thiz;
+        ERR_print_errors_cb(staticCallback, &thiz);
+        return thiz.mSs.str();
+    }
+
+private:
+    static int staticCallback(const char* str, size_t len, void* ctx) {
+        return reinterpret_cast<ErrorQueueString*>(ctx)->callback(str, len);
+    }
+    int callback(const char* str, size_t len) {
+        if (len == 0) return 1; // continue
+        // ERR_print_errors_cb place a new line at the end, but it doesn't say so in the API.
+        if (str[len - 1] == '\n') len -= 1;
+        if (!mIsFirst) {
+            mSs << '\n';
+        }
+        mSs << std::string_view(str, len);
+        mIsFirst = false;
+        return 1; // continue
+    }
+    std::stringstream mSs;
+    bool mIsFirst = true;
+};
+
+// Handles libssl's error queue.
+//
+// Call into any of its member functions to ensure the error queue is properly handled or cleared.
+// If the error queue is not handled or cleared, the destructor will abort.
+class ErrorQueue {
+public:
+    ~ErrorQueue() { LOG_ALWAYS_FATAL_IF(!mHandled); }
+
+    // Clear the error queue.
+    void clear() {
+        ERR_clear_error();
+        mHandled = true;
+    }
+
+    // Stores the error queue in |ssl| into a string, then clears the error queue.
+    std::string toString() {
+        auto ret = ErrorQueueString::toString();
+        // Though ERR_print_errors_cb should have cleared it, it is okay to clear again.
+        clear();
+        return ret;
+    }
+
+    // |sslError| should be from Ssl::getError().
+    // If |sslError| is WANT_READ / WANT_WRITE, poll for POLLIN / POLLOUT respectively. Otherwise
+    // return error. Also return error if |fdTrigger| is triggered before or during poll().
+    status_t pollForSslError(android::base::borrowed_fd fd, int sslError, FdTrigger* fdTrigger,
+                             const char* fnString, int additionalEvent = 0) {
+        switch (sslError) {
+            case SSL_ERROR_WANT_READ:
+                return handlePoll(POLLIN | additionalEvent, fd, fdTrigger, fnString);
+            case SSL_ERROR_WANT_WRITE:
+                return handlePoll(POLLOUT | additionalEvent, fd, fdTrigger, fnString);
+            case SSL_ERROR_SYSCALL: {
+                auto queue = toString();
+                LOG_TLS_DETAIL("%s(): %s. Treating as DEAD_OBJECT. Error queue: %s", fnString,
+                               SSL_error_description(sslError), queue.c_str());
+                return DEAD_OBJECT;
+            }
+            default: {
+                auto queue = toString();
+                ALOGE("%s(): %s. Error queue: %s", fnString, SSL_error_description(sslError),
+                      queue.c_str());
+                return UNKNOWN_ERROR;
+            }
+        }
+    }
+
+private:
+    bool mHandled = false;
+
+    status_t handlePoll(int event, android::base::borrowed_fd fd, FdTrigger* fdTrigger,
+                        const char* fnString) {
+        status_t ret = fdTrigger->triggerablePoll(fd, event);
+        if (ret != OK && ret != DEAD_OBJECT && ret != -ECANCELED) {
+            ALOGE("triggerablePoll error while poll()-ing after %s(): %s", fnString,
+                  statusToString(ret).c_str());
+        }
+        clear();
+        return ret;
+    }
+};
+
+// Helper to call a function, with its return value instantiable.
+template <typename Fn, typename... Args>
+struct FuncCaller {
+    struct Monostate {};
+    static constexpr bool sIsVoid = std::is_void_v<std::invoke_result_t<Fn, Args...>>;
+    using Result = std::conditional_t<sIsVoid, Monostate, std::invoke_result_t<Fn, Args...>>;
+    static inline Result call(Fn fn, Args&&... args) {
+        if constexpr (std::is_void_v<std::invoke_result_t<Fn, Args...>>) {
+            std::invoke(fn, std::forward<Args>(args)...);
+            return {};
+        } else {
+            return std::invoke(fn, std::forward<Args>(args)...);
+        }
+    }
+};
+
+// Helper to Ssl::call(). Returns the result to the SSL_* function as well as an ErrorQueue object.
+template <typename Fn, typename... Args>
+struct SslCaller {
+    using RawCaller = FuncCaller<Fn, SSL*, Args...>;
+    struct ResultAndErrorQueue {
+        typename RawCaller::Result result;
+        ErrorQueue errorQueue;
+    };
+    static inline ResultAndErrorQueue call(Fn fn, SSL* ssl, Args&&... args) {
+        LOG_ALWAYS_FATAL_IF(ssl == nullptr);
+        auto result = RawCaller::call(fn, std::forward<SSL*>(ssl), std::forward<Args>(args)...);
+        return ResultAndErrorQueue{std::move(result), ErrorQueue()};
+    }
+};
+
+// A wrapper over bssl::UniquePtr<SSL>. This class ensures that all SSL_* functions are called
+// through call(), which returns an ErrorQueue object that requires the caller to either handle
+// or clear it.
+// Example:
+//   auto [ret, errorQueue] = ssl.call(SSL_read, buf, size);
+//   if (ret >= 0) errorQueue.clear();
+//   else ALOGE("%s", errorQueue.toString().c_str());
+class Ssl {
+public:
+    explicit Ssl(bssl::UniquePtr<SSL> ssl) : mSsl(std::move(ssl)) {
+        LOG_ALWAYS_FATAL_IF(mSsl == nullptr);
+    }
+
+    template <typename Fn, typename... Args>
+    inline typename SslCaller<Fn, Args...>::ResultAndErrorQueue call(Fn fn, Args&&... args) {
+        return SslCaller<Fn, Args...>::call(fn, mSsl.get(), std::forward<Args>(args)...);
+    }
+
+    int getError(int ret) {
+        LOG_ALWAYS_FATAL_IF(mSsl == nullptr);
+        return SSL_get_error(mSsl.get(), ret);
+    }
+
+private:
+    bssl::UniquePtr<SSL> mSsl;
+};
+
+class RpcTransportTls : public RpcTransport {
+public:
+    RpcTransportTls(android::base::unique_fd socket, Ssl ssl)
+          : mSocket(std::move(socket)), mSsl(std::move(ssl)) {}
+    Result<size_t> peek(void* buf, size_t size) override;
+    status_t interruptableWriteFully(FdTrigger* fdTrigger, const void* data, size_t size) override;
+    status_t interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) override;
+
+private:
+    android::base::unique_fd mSocket;
+    Ssl mSsl;
+
+    static status_t isTriggered(FdTrigger* fdTrigger);
+};
+
+// Error code is errno.
+Result<size_t> RpcTransportTls::peek(void* buf, size_t size) {
+    size_t todo = std::min<size_t>(size, std::numeric_limits<int>::max());
+    auto [ret, errorQueue] = mSsl.call(SSL_peek, buf, static_cast<int>(todo));
+    if (ret < 0) {
+        int err = mSsl.getError(ret);
+        if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
+            // Seen EAGAIN / EWOULDBLOCK on recv(2) / send(2).
+            // Like RpcTransportRaw::peek(), don't handle it here.
+            return Error(EWOULDBLOCK) << "SSL_peek(): " << errorQueue.toString();
+        }
+        return Error() << "SSL_peek(): " << errorQueue.toString();
+    }
+    errorQueue.clear();
+    LOG_TLS_DETAIL("TLS: Peeked %d bytes!", ret);
+    return ret;
+}
+
+status_t RpcTransportTls::isTriggered(FdTrigger* fdTrigger) {
+    auto ret = fdTrigger->isTriggeredPolled();
+    if (!ret.ok()) {
+        ALOGE("%s: %s", __PRETTY_FUNCTION__, ret.error().message().c_str());
+        return ret.error().code() == 0 ? UNKNOWN_ERROR : -ret.error().code();
+    }
+    return OK;
+}
+
+status_t RpcTransportTls::interruptableWriteFully(FdTrigger* fdTrigger, const void* data,
+                                                  size_t size) {
+    auto buffer = reinterpret_cast<const uint8_t*>(data);
+    const uint8_t* end = buffer + size;
+
+    MAYBE_WAIT_IN_FLAKE_MODE;
+
+    // Before doing any I/O, check trigger once. This ensures the trigger is checked at least
+    // once. The trigger is also checked via triggerablePoll() after every SSL_write().
+    if (status_t status = isTriggered(fdTrigger); status != OK) return status;
+
+    while (buffer < end) {
+        size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
+        auto [writeSize, errorQueue] = mSsl.call(SSL_write, buffer, todo);
+        if (writeSize > 0) {
+            buffer += writeSize;
+            errorQueue.clear();
+            continue;
+        }
+        // SSL_write() should never return 0 unless BIO_write were to return 0.
+        int sslError = mSsl.getError(writeSize);
+        // TODO(b/195788248): BIO should contain the FdTrigger, and send(2) / recv(2) should be
+        //   triggerablePoll()-ed. Then additionalEvent is no longer necessary.
+        status_t pollStatus =
+                errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger, "SSL_write", POLLIN);
+        if (pollStatus != OK) return pollStatus;
+        // Do not advance buffer. Try SSL_write() again.
+    }
+    LOG_TLS_DETAIL("TLS: Sent %zu bytes!", size);
+    return OK;
+}
+
+status_t RpcTransportTls::interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) {
+    auto buffer = reinterpret_cast<uint8_t*>(data);
+    uint8_t* end = buffer + size;
+
+    MAYBE_WAIT_IN_FLAKE_MODE;
+
+    // Before doing any I/O, check trigger once. This ensures the trigger is checked at least
+    // once. The trigger is also checked via triggerablePoll() after every SSL_write().
+    if (status_t status = isTriggered(fdTrigger); status != OK) return status;
+
+    while (buffer < end) {
+        size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
+        auto [readSize, errorQueue] = mSsl.call(SSL_read, buffer, todo);
+        if (readSize > 0) {
+            buffer += readSize;
+            errorQueue.clear();
+            continue;
+        }
+        if (readSize == 0) {
+            // SSL_read() only returns 0 on EOF.
+            errorQueue.clear();
+            return DEAD_OBJECT;
+        }
+        int sslError = mSsl.getError(readSize);
+        status_t pollStatus =
+                errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger, "SSL_read");
+        if (pollStatus != OK) return pollStatus;
+        // Do not advance buffer. Try SSL_read() again.
+    }
+    LOG_TLS_DETAIL("TLS: Received %zu bytes!", size);
+    return OK;
+}
+
+// For |ssl|, set internal FD to |fd|, and do handshake. Handshake is triggerable by |fdTrigger|.
+bool setFdAndDoHandshake(Ssl* ssl, android::base::borrowed_fd fd, FdTrigger* fdTrigger) {
+    bssl::UniquePtr<BIO> bio = newSocketBio(fd);
+    TEST_AND_RETURN(false, bio != nullptr);
+    auto [_, errorQueue] = ssl->call(SSL_set_bio, bio.get(), bio.get());
+    (void)bio.release(); // SSL_set_bio takes ownership.
+    errorQueue.clear();
+
+    MAYBE_WAIT_IN_FLAKE_MODE;
+
+    while (true) {
+        auto [ret, errorQueue] = ssl->call(SSL_do_handshake);
+        if (ret > 0) {
+            errorQueue.clear();
+            return true;
+        }
+        if (ret == 0) {
+            // SSL_do_handshake() only returns 0 on EOF.
+            ALOGE("SSL_do_handshake(): EOF: %s", errorQueue.toString().c_str());
+            return false;
+        }
+        int sslError = ssl->getError(ret);
+        status_t pollStatus =
+                errorQueue.pollForSslError(fd, sslError, fdTrigger, "SSL_do_handshake");
+        if (pollStatus != OK) return false;
+    }
+}
+
+class RpcTransportCtxTls : public RpcTransportCtx {
+public:
+    template <typename Impl,
+              typename = std::enable_if_t<std::is_base_of_v<RpcTransportCtxTls, Impl>>>
+    static std::unique_ptr<RpcTransportCtxTls> create();
+    std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
+                                               FdTrigger* fdTrigger) const override;
+    std::string getCertificate(CertificateFormat) const override;
+    status_t addTrustedPeerCertificate(CertificateFormat, std::string_view cert) override;
+
+protected:
+    virtual void preHandshake(Ssl* ssl) const = 0;
+    bssl::UniquePtr<SSL_CTX> mCtx;
+};
+
+std::string RpcTransportCtxTls::getCertificate(CertificateFormat) const {
+    // TODO(b/195166979): return certificate here
+    return {};
+}
+
+status_t RpcTransportCtxTls::addTrustedPeerCertificate(CertificateFormat, std::string_view) {
+    // TODO(b/195166979): set certificate here
+    return OK;
+}
+
+// Common implementation for creating server and client contexts. The child class, |Impl|, is
+// provided as a template argument so that this function can initialize an |Impl| object.
+template <typename Impl, typename>
+std::unique_ptr<RpcTransportCtxTls> RpcTransportCtxTls::create() {
+    bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+    TEST_AND_RETURN(nullptr, ctx != nullptr);
+
+    auto evp_pkey = makeKeyPairForSelfSignedCert();
+    TEST_AND_RETURN(nullptr, evp_pkey != nullptr);
+    auto cert = makeSelfSignedCert(evp_pkey.get(), kCertValidDays);
+    TEST_AND_RETURN(nullptr, cert != nullptr);
+    TEST_AND_RETURN(nullptr, SSL_CTX_use_PrivateKey(ctx.get(), evp_pkey.get()));
+    TEST_AND_RETURN(nullptr, SSL_CTX_use_certificate(ctx.get(), cert.get()));
+
+    // TODO(b/195166979): peer should send certificate in a different channel, and this class
+    //  should verify it here.
+    SSL_CTX_set_custom_verify(ctx.get(), SSL_VERIFY_PEER,
+                              [](SSL*, uint8_t*) -> ssl_verify_result_t { return ssl_verify_ok; });
+
+    // Require at least TLS 1.3
+    TEST_AND_RETURN(nullptr, SSL_CTX_set_min_proto_version(ctx.get(), TLS1_3_VERSION));
+
+    if constexpr (SHOULD_LOG_TLS_DETAIL) { // NOLINT
+        SSL_CTX_set_info_callback(ctx.get(), sslDebugLog);
+    }
+
+    auto ret = std::make_unique<Impl>();
+    ret->mCtx = std::move(ctx);
+    return ret;
+}
+
+std::unique_ptr<RpcTransport> RpcTransportCtxTls::newTransport(android::base::unique_fd fd,
+                                                               FdTrigger* fdTrigger) const {
+    bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get()));
+    TEST_AND_RETURN(nullptr, ssl != nullptr);
+    Ssl wrapped(std::move(ssl));
+
+    preHandshake(&wrapped);
+    TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, fd, fdTrigger));
+    return std::make_unique<RpcTransportTls>(std::move(fd), std::move(wrapped));
+}
+
+class RpcTransportCtxTlsServer : public RpcTransportCtxTls {
+protected:
+    void preHandshake(Ssl* ssl) const override {
+        ssl->call(SSL_set_accept_state).errorQueue.clear();
+    }
+};
+
+class RpcTransportCtxTlsClient : public RpcTransportCtxTls {
+protected:
+    void preHandshake(Ssl* ssl) const override {
+        ssl->call(SSL_set_connect_state).errorQueue.clear();
+    }
+};
+
+} // namespace
+
+std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newServerCtx() const {
+    return android::RpcTransportCtxTls::create<RpcTransportCtxTlsServer>();
+}
+
+std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newClientCtx() const {
+    return android::RpcTransportCtxTls::create<RpcTransportCtxTlsClient>();
+}
+
+const char* RpcTransportCtxFactoryTls::toCString() const {
+    return "tls";
+}
+
+std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTls::make() {
+    return std::unique_ptr<RpcTransportCtxFactoryTls>(new RpcTransportCtxFactoryTls());
+}
+
+} // namespace android
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 02052ad..fd8ac62 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -245,9 +245,10 @@
     template<typename T>
     status_t            writeNullableParcelable(const std::optional<T>& parcelable)
             { return writeData(parcelable); }
-    template<typename T>
-    status_t            writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")))
-            { return writeData(parcelable); }
+    template <typename T>
+    status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) {
+        return writeData(parcelable);
+    }
 
     status_t            writeParcelable(const Parcelable& parcelable);
 
@@ -401,9 +402,10 @@
     template<typename T>
     status_t            readParcelable(std::optional<T>* parcelable) const
             { return readData(parcelable); }
-    template<typename T>
-    status_t            readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")))
-            { return readData(parcelable); }
+    template <typename T>
+    status_t readParcelable(std::unique_ptr<T>* parcelable) const {
+        return readData(parcelable);
+    }
 
     // If strong binder would be nullptr, readStrongBinder() returns an error.
     // TODO: T must be derived from IInterface, fix for clarity.
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 761c50d..6e6eb74 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -18,7 +18,6 @@
 #include <android-base/unique_fd.h>
 #include <binder/IBinder.h>
 #include <binder/RpcAddress.h>
-#include <binder/RpcSession.h>
 #include <binder/RpcTransport.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index 1b69519..8d08b34 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -29,7 +29,13 @@
 
 class FdTrigger;
 
+enum class CertificateFormat {
+    PEM,
+    // TODO(b/195166979): support other formats, e.g. DER
+};
+
 // Represents a socket connection.
+// No thread-safety is guaranteed for these APIs.
 class RpcTransport {
 public:
     virtual ~RpcTransport() = default;
@@ -53,22 +59,43 @@
 };
 
 // Represents the context that generates the socket connection.
+// All APIs are thread-safe. See RpcTransportCtxRaw and RpcTransportCtxTls for details.
 class RpcTransportCtx {
 public:
     virtual ~RpcTransportCtx() = default;
 
     // Create a new RpcTransport object.
     //
-    // Implemenion details: for TLS, this function may incur I/O. |fdTrigger| may be used
+    // Implementation details: for TLS, this function may incur I/O. |fdTrigger| may be used
     // to interrupt I/O. This function blocks until handshake is finished.
     [[nodiscard]] virtual std::unique_ptr<RpcTransport> newTransport(
             android::base::unique_fd fd, FdTrigger *fdTrigger) const = 0;
 
+    // Return the preconfigured certificate of this context.
+    //
+    // Implementation details:
+    // - For raw sockets, this always returns empty string.
+    // - For TLS, this returns the certificate. See RpcTransportTls for details.
+    [[nodiscard]] virtual std::string getCertificate(CertificateFormat format) const = 0;
+
+    // Add a trusted peer certificate. Peers presenting this certificate are accepted.
+    //
+    // Caller must ensure that newTransport() are called after all trusted peer certificates
+    // are added. Otherwise, RpcTransport-s created before may not trust peer certificates
+    // added later.
+    //
+    // Implementation details:
+    // - For raw sockets, this always returns OK.
+    // - For TLS, this adds trusted peer certificate. See RpcTransportTls for details.
+    [[nodiscard]] virtual status_t addTrustedPeerCertificate(CertificateFormat format,
+                                                             std::string_view cert) = 0;
+
 protected:
     RpcTransportCtx() = default;
 };
 
 // A factory class that generates RpcTransportCtx.
+// All APIs are thread-safe.
 class RpcTransportCtxFactory {
 public:
     virtual ~RpcTransportCtxFactory() = default;
diff --git a/libs/binder/include_tls/binder/RpcTransportTls.h b/libs/binder/include_tls/binder/RpcTransportTls.h
new file mode 100644
index 0000000..531aaa9
--- /dev/null
+++ b/libs/binder/include_tls/binder/RpcTransportTls.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Wraps the transport layer of RPC. Implementation uses TLS.
+
+#pragma once
+
+#include <binder/RpcTransport.h>
+
+namespace android {
+
+// RpcTransportCtxFactory with TLS enabled with self-signed certificate.
+class RpcTransportCtxFactoryTls : public RpcTransportCtxFactory {
+public:
+    static std::unique_ptr<RpcTransportCtxFactory> make();
+
+    std::unique_ptr<RpcTransportCtx> newServerCtx() const override;
+    std::unique_ptr<RpcTransportCtx> newClientCtx() const override;
+    const char* toCString() const override;
+
+private:
+    RpcTransportCtxFactoryTls() = default;
+};
+
+} // namespace android
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 2abb6f7..11e9fc5 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -82,8 +82,8 @@
         const String16& currentDescriptor = mClazz->getInterfaceDescriptor();
         if (newDescriptor == currentDescriptor) {
             LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
-                       << "' match during associateClass, but they are different class objects. "
-                          "Class descriptor collision?";
+                       << "' match during associateClass, but they are different class objects ("
+                       << clazz << " vs " << mClazz << "). Class descriptor collision?";
         } else {
             LOG(ERROR) << __func__
                        << ": Class cannot be associated on object which already has a class. "
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 5092d87..563d011 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -469,6 +469,22 @@
 }
 
 /**
+ * Convenience API for writing a nullable parcelable.
+ */
+template <typename P>
+static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel,
+                                                              const std::unique_ptr<P>& p) {
+    if (!p) {
+        return AParcel_writeInt32(parcel, 0);  // null
+    }
+    binder_status_t status = AParcel_writeInt32(parcel, 1);  // non-null
+    if (status != STATUS_OK) {
+        return status;
+    }
+    return p->writeToParcel(parcel);
+}
+
+/**
  * Convenience API for reading a nullable parcelable.
  */
 template <typename P>
@@ -488,6 +504,25 @@
 }
 
 /**
+ * Convenience API for reading a nullable parcelable.
+ */
+template <typename P>
+static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel,
+                                                             std::unique_ptr<P>* p) {
+    int32_t null;
+    binder_status_t status = AParcel_readInt32(parcel, &null);
+    if (status != STATUS_OK) {
+        return status;
+    }
+    if (null == 0) {
+        p->reset();
+        return STATUS_OK;
+    }
+    *p = std::make_unique<P>();
+    return (*p)->readFromParcel(parcel);
+}
+
+/**
  * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
  */
 template <typename P>
diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp
index 488009f..8ee396e 100644
--- a/libs/binder/ndk/tests/Android.bp
+++ b/libs/binder/ndk/tests/Android.bp
@@ -71,7 +71,7 @@
     srcs: ["libbinder_ndk_unit_test.cpp"],
     static_libs: [
         "IBinderNdkUnitTest-cpp",
-        "IBinderNdkUnitTest-ndk_platform",
+        "IBinderNdkUnitTest-ndk",
     ],
     test_suites: [
         "general-tests",
@@ -88,8 +88,8 @@
     ],
     static_libs: [
         "IBinderVendorDoubleLoadTest-cpp",
-        "IBinderVendorDoubleLoadTest-ndk_platform",
-        "libbinder_aidl_test_stub-ndk_platform",
+        "IBinderVendorDoubleLoadTest-ndk",
+        "libbinder_aidl_test_stub-ndk",
     ],
     // critical that libbinder/libbinder_ndk are shared for VTS
     shared_libs: [
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 956ecfe..56c6165 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -764,6 +764,30 @@
     }
 }
 
+impl<T: Serialize> Serialize for Box<T> {
+    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+        Serialize::serialize(&**self, parcel)
+    }
+}
+
+impl<T: Deserialize> Deserialize for Box<T> {
+    fn deserialize(parcel: &Parcel) -> Result<Self> {
+        Deserialize::deserialize(parcel).map(Box::new)
+    }
+}
+
+impl<T: SerializeOption> SerializeOption for Box<T> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+        SerializeOption::serialize_option(this.map(|inner| &**inner), parcel)
+    }
+}
+
+impl<T: DeserializeOption> DeserializeOption for Box<T> {
+    fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+        DeserializeOption::deserialize_option(parcel).map(|t| t.map(Box::new))
+    }
+}
+
 #[test]
 fn test_custom_parcelable() {
     use crate::binder::Interface;
diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp
index 607860f..ecc61f4 100644
--- a/libs/binder/rust/tests/Android.bp
+++ b/libs/binder/rust/tests/Android.bp
@@ -50,7 +50,7 @@
         "libbinder_ndk",
     ],
     static_libs: [
-        "IBinderRustNdkInteropTest-ndk_platform",
+        "IBinderRustNdkInteropTest-ndk",
         "libbinder_ndk_rust_interop",
     ],
     test_suites: ["general-tests"],
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 24afcf6..2546edb 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -145,6 +145,7 @@
     defaults: [
         "binder_test_defaults",
         "libbinder_ndk_host_user",
+        "libbinder_tls_shared_deps",
     ],
 
     srcs: [
@@ -159,8 +160,9 @@
         "liblog",
     ],
     static_libs: [
+        "libbinder_tls_static",
         "binderRpcTestIface-cpp",
-        "binderRpcTestIface-ndk_platform",
+        "binderRpcTestIface-ndk",
     ],
     test_suites: ["general-tests"],
     require_root: true,
@@ -296,7 +298,7 @@
     ],
     static_libs: [
         "binderStabilityTestIface-cpp",
-        "binderStabilityTestIface-ndk_platform",
+        "binderStabilityTestIface-ndk",
     ],
 
     test_suites: ["device-tests", "vts"],
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 15ccae9..35db444 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -31,6 +31,7 @@
 #include <binder/RpcSession.h>
 #include <binder/RpcTransport.h>
 #include <binder/RpcTransportRaw.h>
+#include <binder/RpcTransportTls.h>
 #include <gtest/gtest.h>
 
 #include <chrono>
@@ -54,16 +55,18 @@
               RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
 const char* kLocalInetAddress = "127.0.0.1";
 
-enum class RpcSecurity { RAW };
+enum class RpcSecurity { RAW, TLS };
 
 static inline std::vector<RpcSecurity> RpcSecurityValues() {
-    return {RpcSecurity::RAW};
+    return {RpcSecurity::RAW, RpcSecurity::TLS};
 }
 
 static inline std::unique_ptr<RpcTransportCtxFactory> newFactory(RpcSecurity rpcSecurity) {
     switch (rpcSecurity) {
         case RpcSecurity::RAW:
             return RpcTransportCtxFactoryRaw::make();
+        case RpcSecurity::TLS:
+            return RpcTransportCtxFactoryTls::make();
         default:
             LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", rpcSecurity);
     }
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index a0032ae..cda9e19 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -52,14 +52,14 @@
     ],
 
     shared_libs: [
-        "android.hardware.graphics.common-V2-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk",
         "android.hardware.graphics.mapper@4.0",
         "libhidlbase",
         "liblog",
     ],
 
     export_shared_lib_headers: [
-        "android.hardware.graphics.common-V2-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk",
         "android.hardware.graphics.mapper@4.0",
         "libhidlbase",
     ],
diff --git a/libs/input/VelocityControl.cpp b/libs/input/VelocityControl.cpp
index bcf55b0..03c49cc 100644
--- a/libs/input/VelocityControl.cpp
+++ b/libs/input/VelocityControl.cpp
@@ -18,7 +18,7 @@
 //#define LOG_NDEBUG 0
 
 // Log debug messages about acceleration.
-#define DEBUG_ACCELERATION 0
+static constexpr bool DEBUG_ACCELERATION = false;
 
 #include <math.h>
 #include <limits.h>
@@ -52,10 +52,10 @@
 void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
     if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
         if (eventTime >= mLastMovementTime + STOP_TIME) {
-#if DEBUG_ACCELERATION
-            ALOGD("VelocityControl: stopped, last movement was %0.3fms ago",
-                    (eventTime - mLastMovementTime) * 0.000001f);
-#endif
+            if (DEBUG_ACCELERATION && mLastMovementTime != LLONG_MIN) {
+                ALOGD("VelocityControl: stopped, last movement was %0.3fms ago",
+                           (eventTime - mLastMovementTime) * 0.000001f);
+            }
             reset();
         }
 
@@ -83,19 +83,20 @@
                         * (mParameters.acceleration - 1);
             }
 
-#if DEBUG_ACCELERATION
-            ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
-                    "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
-                    mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
-                    mParameters.acceleration,
-                    vx, vy, speed, scale / mParameters.scale);
-#endif
+            if (DEBUG_ACCELERATION) {
+                ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
+                        "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
+                        mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
+                        mParameters.acceleration,
+                        vx, vy, speed, scale / mParameters.scale);
+            }
+
         } else {
-#if DEBUG_ACCELERATION
-            ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
-                    mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
-                    mParameters.acceleration);
-#endif
+            if (DEBUG_ACCELERATION) {
+                ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
+                        mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
+                        mParameters.acceleration);
+            }
         }
 
         if (deltaX) {
diff --git a/libs/renderengine/OWNERS b/libs/renderengine/OWNERS
index c478506..5d23a5e 100644
--- a/libs/renderengine/OWNERS
+++ b/libs/renderengine/OWNERS
@@ -1,3 +1,4 @@
+adyabr@google.com
 alecmouri@google.com
 djsollen@google.com
 jreck@google.com
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 07760ab..26c874e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -89,7 +89,7 @@
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.allocator@4.0",
-        "android.hardware.graphics.common-V2-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.1",
@@ -106,7 +106,7 @@
 
     export_shared_lib_headers: [
         "android.hardware.graphics.common@1.2",
-        "android.hardware.graphics.common-V2-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk",
         "android.hardware.graphics.mapper@4.0",
         "libgralloctypes",
     ],
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index cbdb1d0..bfdc02c 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -905,6 +905,13 @@
             mTiltXScale = M_PI / 180;
             mTiltYScale = M_PI / 180;
 
+            if (mRawPointerAxes.tiltX.resolution) {
+                mTiltXScale = 1.0 / mRawPointerAxes.tiltX.resolution;
+            }
+            if (mRawPointerAxes.tiltY.resolution) {
+                mTiltYScale = 1.0 / mRawPointerAxes.tiltY.resolution;
+            }
+
             mOrientedRanges.haveTilt = true;
 
             mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
diff --git a/services/memtrackproxy/Android.bp b/services/memtrackproxy/Android.bp
index 7d78f3b..3233cc9 100644
--- a/services/memtrackproxy/Android.bp
+++ b/services/memtrackproxy/Android.bp
@@ -32,7 +32,7 @@
         "libcutils",
         "libutils",
         "android.hardware.memtrack@1.0",
-        "android.hardware.memtrack-V1-ndk_platform",
+        "android.hardware.memtrack-V1-ndk",
     ],
     srcs: [
         "MemtrackProxy.cpp",
@@ -45,6 +45,6 @@
     ],
     export_shared_lib_headers: [
         "android.hardware.memtrack@1.0",
-        "android.hardware.memtrack-V1-ndk_platform",
+        "android.hardware.memtrack-V1-ndk",
     ],
 }
diff --git a/services/memtrackproxy/test/Android.bp b/services/memtrackproxy/test/Android.bp
index f943761..1dc21bf 100644
--- a/services/memtrackproxy/test/Android.bp
+++ b/services/memtrackproxy/test/Android.bp
@@ -29,7 +29,7 @@
     shared_libs: [
         "libbinder_ndk",
         "libmemtrackproxy",
-        "android.hardware.memtrack-V1-ndk_platform",
+        "android.hardware.memtrack-V1-ndk",
     ],
     test_suites: ["general-tests"],
     require_root: true,
diff --git a/services/surfaceflinger/TimeStats/OWNERS b/services/surfaceflinger/TimeStats/OWNERS
index ded3ebb..d78f5e2 100644
--- a/services/surfaceflinger/TimeStats/OWNERS
+++ b/services/surfaceflinger/TimeStats/OWNERS
@@ -1 +1,2 @@
+adyabr@google.com
 alecmouri@google.com
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 15744a1..81e39c7 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -53,7 +53,7 @@
         "libtrace_proto",
     ],
     shared_libs: [
-        "android.hardware.graphics.common-V2-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.composer@2.1",
         "libandroid",