Merge "libbinder: don't ignore sendDecStrong error"
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index fa63db5..677d6c7 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -60,6 +60,7 @@
     MOCK_METHOD1(isDeclared, bool(const String16&));
     MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&));
     MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&));
+    MOCK_METHOD1(getConnectionInfo, std::optional<ConnectionInfo>(const String16&));
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
 };
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 6f08f74..cba7c4b 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -22,9 +22,10 @@
 #include <thread>
 #include <vector>
 
-#include <gtest/gtest.h>
-#include <gmock/gmock.h>
+#include <android-base/parseint.h>
 #include <android/hardware/tests/inheritance/1.0/IChild.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
 #include <hidl/HidlTransportSupport.h>
 #include <vintf/parse_xml.h>
 
@@ -77,6 +78,13 @@
             content += "\n";
             content += option.c_str();
         }
+        if (options.size() > 0) {
+            uint64_t len;
+            if (android::base::ParseUint(options[0], &len)) {
+                content += "\n";
+                content += std::string(len, 'X');
+            }
+        }
         ssize_t written = write(fd, content.c_str(), content.size());
         if (written != (ssize_t)content.size()) {
             LOG(WARNING) << "SERVER(Child) debug writes " << written << " bytes < "
@@ -189,6 +197,16 @@
     EXPECT_THAT(err.str(), HasSubstr("does not exist"));
 }
 
+TEST_F(DebugTest, DebugLarge) {
+    EXPECT_EQ(0u, callMain(lshal, {
+        "lshal", "debug", "android.hardware.tests.inheritance@1.0::IChild/default", "10000"
+    }));
+    EXPECT_THAT(out.str(),
+                StrEq("android.hardware.tests.inheritance@1.0::IChild\n10000\n" +
+                      std::string(10000, 'X')));
+    EXPECT_THAT(err.str(), IsEmpty());
+}
+
 TEST_F(DebugTest, DebugParent) {
     EXPECT_EQ(0u, callMain(lshal, {
         "lshal", "debug", "android.hardware.tests.inheritance@1.0::IParent", "calling parent"
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 90db509..4e44ac7 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -121,6 +121,35 @@
     return updatableViaApex;
 }
 
+static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
+    AidlName aname;
+    if (!AidlName::fill(name, &aname)) return std::nullopt;
+
+    std::optional<std::string> ip;
+    std::optional<uint64_t> port;
+    forEachManifest([&](const ManifestWithDescription& mwd) {
+        mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+            if (manifestInstance.format() != vintf::HalFormat::AIDL) return true;
+            if (manifestInstance.package() != aname.package) return true;
+            if (manifestInstance.interface() != aname.iface) return true;
+            if (manifestInstance.instance() != aname.instance) return true;
+            ip = manifestInstance.ip();
+            port = manifestInstance.port();
+            return false; // break (libvintf uses opposite convention)
+        });
+        return false; // continue
+    });
+
+    if (ip.has_value() && port.has_value()) {
+        ConnectionInfo info;
+        info.ipAddress = *ip;
+        info.port = *port;
+        return std::make_optional<ConnectionInfo>(info);
+    } else {
+        return std::nullopt;
+    }
+}
+
 static std::vector<std::string> getVintfInstances(const std::string& interface) {
     size_t lastDot = interface.rfind('.');
     if (lastDot == std::string::npos) {
@@ -437,6 +466,22 @@
     return Status::ok();
 }
 
+Status ServiceManager::getConnectionInfo(const std::string& name,
+                                         std::optional<ConnectionInfo>* outReturn) {
+    auto ctx = mAccess->getCallingContext();
+
+    if (!mAccess->canFind(ctx, name)) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    *outReturn = std::nullopt;
+
+#ifndef VENDORSERVICEMANAGER
+    *outReturn = getVintfConnectionInfo(name);
+#endif
+    return Status::ok();
+}
+
 void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who,
                                     ServiceCallbackMap::iterator* it,
                                     bool* found) {
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 4f23c21..5e40319 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -24,6 +24,7 @@
 
 namespace android {
 
+using os::ConnectionInfo;
 using os::IClientCallback;
 using os::IServiceCallback;
 using os::ServiceDebugInfo;
@@ -48,6 +49,8 @@
     binder::Status getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override;
     binder::Status updatableViaApex(const std::string& name,
                                     std::optional<std::string>* outReturn) override;
+    binder::Status getConnectionInfo(const std::string& name,
+                                     std::optional<ConnectionInfo>* outReturn) override;
     binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service,
                                           const sp<IClientCallback>& cb) override;
     binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 6cb45ca..aff9e25 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -287,6 +287,7 @@
 filegroup {
     name: "libbinder_aidl",
     srcs: [
+        "aidl/android/os/ConnectionInfo.aidl",
         "aidl/android/os/IClientCallback.aidl",
         "aidl/android/os/IServiceCallback.aidl",
         "aidl/android/os/IServiceManager.aidl",
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 6e318ea..aff9e0d 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -78,6 +78,7 @@
     bool isDeclared(const String16& name) override;
     Vector<String16> getDeclaredInstances(const String16& interface) override;
     std::optional<String16> updatableViaApex(const String16& name) override;
+    std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override;
 
     // for legacy ABI
     const String16& getInterfaceDescriptor() const override {
@@ -426,6 +427,21 @@
     return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt;
 }
 
+std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnectionInfo(
+        const String16& name) {
+    std::optional<os::ConnectionInfo> connectionInfo;
+    if (Status status =
+                mTheRealServiceManager->getConnectionInfo(String8(name).c_str(), &connectionInfo);
+        !status.isOk()) {
+        ALOGW("Failed to get ConnectionInfo for %s: %s", String8(name).c_str(),
+              status.toString8().c_str());
+    }
+    return connectionInfo.has_value()
+            ? std::make_optional<IServiceManager::ConnectionInfo>(
+                      {connectionInfo->ipAddress, static_cast<unsigned int>(connectionInfo->port)})
+            : std::nullopt;
+}
+
 #ifndef __ANDROID__
 // ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API.
 // The internal implementation of the AIDL interface android::os::IServiceManager calls into
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9f95167..6644187 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -233,7 +233,7 @@
                 ALOGE("null proxy");
             } else {
                 if (proxy->isRpcBinder()) {
-                    ALOGE("Sending a socket binder over RPC is prohibited");
+                    ALOGE("Sending a socket binder over kernel binder is prohibited");
                     return INVALID_OPERATION;
                 }
             }
diff --git a/libs/binder/aidl/android/os/ConnectionInfo.aidl b/libs/binder/aidl/android/os/ConnectionInfo.aidl
new file mode 100644
index 0000000..160c9ea
--- /dev/null
+++ b/libs/binder/aidl/android/os/ConnectionInfo.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package android.os;
+
+/**
+ * Remote connection info associated with a declared service
+ * @hide
+ */
+parcelable ConnectionInfo {
+    /**
+     * IP address that the service is listening on.
+     */
+    @utf8InCpp String ipAddress;
+    /**
+     * Port number that the service is listening on. Actual value is an unsigned integer.
+     */
+    int port;
+}
+
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 75c4092..5880c0a 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -19,6 +19,7 @@
 import android.os.IClientCallback;
 import android.os.IServiceCallback;
 import android.os.ServiceDebugInfo;
+import android.os.ConnectionInfo;
 
 /**
  * Basic interface for finding and publishing system services.
@@ -113,6 +114,11 @@
     @nullable @utf8InCpp String updatableViaApex(@utf8InCpp String name);
 
     /**
+     * If connection info is available for the given instance, returns the ConnectionInfo
+     */
+    @nullable ConnectionInfo getConnectionInfo(@utf8InCpp String name);
+
+    /**
      * Request a callback when the number of clients of the service changes.
      * Used by LazyServiceRegistrar to dynamically stop services that have no clients.
      */
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index d152005..a48075d 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -15,11 +15,9 @@
  */
 
 #pragma once
-
 #include <binder/IInterface.h>
 #include <utils/Vector.h>
 #include <utils/String16.h>
-
 #include <optional>
 
 namespace android {
@@ -107,6 +105,16 @@
      * this can be updated.
      */
     virtual std::optional<String16> updatableViaApex(const String16& name) = 0;
+
+    /**
+     * If this instance has declared remote connection information, returns
+     * the ConnectionInfo.
+     */
+    struct ConnectionInfo {
+        std::string ipAddress;
+        unsigned int port;
+    };
+    virtual std::optional<ConnectionInfo> getConnectionInfo(const String16& name) = 0;
 };
 
 sp<IServiceManager> defaultServiceManager();
diff --git a/libs/binder/ndk/status.cpp b/libs/binder/ndk/status.cpp
index a8ae441..8ed91a5 100644
--- a/libs/binder/ndk/status.cpp
+++ b/libs/binder/ndk/status.cpp
@@ -20,6 +20,7 @@
 #include <android-base/logging.h>
 
 using ::android::status_t;
+using ::android::statusToString;
 using ::android::binder::Status;
 
 AStatus* AStatus_newOk() {
@@ -126,7 +127,7 @@
             return STATUS_UNKNOWN_ERROR;
 
         default:
-            LOG(WARNING) << __func__ << ": Unknown status_t (" << status
+            LOG(WARNING) << __func__ << ": Unknown status_t (" << statusToString(status)
                          << ") pruned into STATUS_UNKNOWN_ERROR";
             return STATUS_UNKNOWN_ERROR;
     }
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 9811cdf..23e34aa 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -157,6 +157,11 @@
                                              std::optional<std::string>* _aidl_return) override {
         return mImpl->updatableViaApex(name, _aidl_return);
     }
+    android::binder::Status getConnectionInfo(
+            const std::string& name,
+            std::optional<android::os::ConnectionInfo>* _aidl_return) override {
+        return mImpl->getConnectionInfo(name, _aidl_return);
+    }
     android::binder::Status registerClientCallback(
             const std::string&, const android::sp<android::IBinder>&,
             const android::sp<android::os::IClientCallback>&) override {
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 23c1b14..71c0e86 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -206,7 +206,10 @@
 
 cc_benchmark {
     name: "binderRpcBenchmark",
-    defaults: ["binder_test_defaults"],
+    defaults: [
+        "binder_test_defaults",
+        "libbinder_tls_shared_deps",
+    ],
     host_supported: true,
     target: {
         darwin: {
@@ -216,6 +219,7 @@
     srcs: [
         "binderRpcBenchmark.cpp",
         "IBinderRpcBenchmark.aidl",
+        "RpcAuthTesting.cpp",
     ],
     shared_libs: [
         "libbase",
@@ -223,6 +227,9 @@
         "liblog",
         "libutils",
     ],
+    static_libs: [
+        "libbinder_tls_static",
+    ],
 }
 
 cc_test {
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 55aa57b..0477d50 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -21,8 +21,14 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <binder/RpcCertificateFormat.h>
+#include <binder/RpcCertificateVerifier.h>
 #include <binder/RpcServer.h>
 #include <binder/RpcSession.h>
+#include <binder/RpcTlsUtils.h>
+#include <binder/RpcTransportRaw.h>
+#include <binder/RpcTransportTls.h>
+#include <openssl/ssl.h>
 
 #include <thread>
 
@@ -31,6 +37,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include "RpcAuthTesting.h"
+
 using android::BBinder;
 using android::defaultServiceManager;
 using android::IBinder;
@@ -39,8 +47,14 @@
 using android::IServiceManager;
 using android::OK;
 using android::ProcessState;
+using android::RpcAuthPreSigned;
+using android::RpcCertificateFormat;
+using android::RpcCertificateVerifier;
 using android::RpcServer;
 using android::RpcSession;
+using android::RpcTransportCtxFactory;
+using android::RpcTransportCtxFactoryRaw;
+using android::RpcTransportCtxFactoryTls;
 using android::sp;
 using android::status_t;
 using android::statusToString;
@@ -65,15 +79,37 @@
 enum Transport {
     KERNEL,
     RPC,
+    RPC_TLS,
 };
 
 static const std::initializer_list<int64_t> kTransportList = {
 #ifdef __BIONIC__
         Transport::KERNEL,
 #endif
-        Transport::RPC};
+        Transport::RPC,
+        Transport::RPC_TLS,
+};
+
+// Certificate validation happens during handshake and does not affect the result of benchmarks.
+// Skip certificate validation to simplify the setup process.
+class RpcCertificateVerifierNoOp : public RpcCertificateVerifier {
+public:
+    status_t verify(const SSL*, uint8_t*) override { return OK; }
+};
+
+std::unique_ptr<RpcTransportCtxFactory> makeFactoryTls() {
+    auto pkey = android::makeKeyPairForSelfSignedCert();
+    CHECK_NE(pkey.get(), nullptr);
+    auto cert = android::makeSelfSignedCert(pkey.get(), android::kCertValidSeconds);
+    CHECK_NE(cert.get(), nullptr);
+
+    auto verifier = std::make_shared<RpcCertificateVerifierNoOp>();
+    auto auth = std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
+    return RpcTransportCtxFactoryTls::make(verifier, std::move(auth));
+}
 
 static sp<RpcSession> gSession = RpcSession::make();
+static sp<RpcSession> gSessionTls = RpcSession::make(makeFactoryTls());
 #ifdef __BIONIC__
 static const String16 kKernelBinderInstance = String16(u"binderRpcBenchmark-control");
 static sp<IBinder> gKernelBinder;
@@ -88,6 +124,8 @@
 #endif
         case RPC:
             return gSession->getRootObject();
+        case RPC_TLS:
+            return gSessionTls->getRootObject();
         default:
             LOG(FATAL) << "Unknown transport value: " << transport;
             return nullptr;
@@ -169,26 +207,35 @@
 }
 BENCHMARK(BM_repeatBinder)->ArgsProduct({kTransportList});
 
+void forkRpcServer(const char* addr, const sp<RpcServer>& server) {
+    if (0 == fork()) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
+        server->setRootObject(sp<MyBinderRpcBenchmark>::make());
+        server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+        CHECK_EQ(OK, server->setupUnixDomainServer(addr));
+        server->join();
+        exit(1);
+    }
+}
+
+void setupClient(const sp<RpcSession>& session, const char* addr) {
+    status_t status;
+    for (size_t tries = 0; tries < 5; tries++) {
+        usleep(10000);
+        status = session->setupUnixDomainClient(addr);
+        if (status == OK) break;
+    }
+    CHECK_EQ(status, OK) << "Could not connect: " << addr << ": " << statusToString(status).c_str();
+}
+
 int main(int argc, char** argv) {
     ::benchmark::Initialize(&argc, argv);
     if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
 
-    std::string addr = std::string(getenv("TMPDIR") ?: "/tmp") + "/binderRpcBenchmark";
-    (void)unlink(addr.c_str());
-
     std::cerr << "Tests suffixes:" << std::endl;
     std::cerr << "\t.../" << Transport::KERNEL << " is KERNEL" << std::endl;
     std::cerr << "\t.../" << Transport::RPC << " is RPC" << std::endl;
-
-    if (0 == fork()) {
-        prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
-        sp<RpcServer> server = RpcServer::make();
-        server->setRootObject(sp<MyBinderRpcBenchmark>::make());
-        server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
-        CHECK_EQ(OK, server->setupUnixDomainServer(addr.c_str()));
-        server->join();
-        exit(1);
-    }
+    std::cerr << "\t.../" << Transport::RPC_TLS << " is RPC with TLS" << std::endl;
 
 #ifdef __BIONIC__
     if (0 == fork()) {
@@ -207,13 +254,17 @@
     CHECK_NE(nullptr, gKernelBinder.get());
 #endif
 
-    status_t status;
-    for (size_t tries = 0; tries < 5; tries++) {
-        usleep(10000);
-        status = gSession->setupUnixDomainClient(addr.c_str());
-        if (status == OK) break;
-    }
-    CHECK_EQ(status, OK) << "Could not connect: " << statusToString(status).c_str();
+    std::string tmp = getenv("TMPDIR") ?: "/tmp";
+
+    std::string addr = tmp + "/binderRpcBenchmark";
+    (void)unlink(addr.c_str());
+    forkRpcServer(addr.c_str(), RpcServer::make(RpcTransportCtxFactoryRaw::make()));
+    setupClient(gSession, addr.c_str());
+
+    std::string tlsAddr = tmp + "/binderRpcTlsBenchmark";
+    (void)unlink(tlsAddr.c_str());
+    forkRpcServer(tlsAddr.c_str(), RpcServer::make(makeFactoryTls()));
+    setupClient(gSessionTls, tlsAddr.c_str());
 
     ::benchmark::RunSpecifiedBenchmarks();
     return 0;
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 0e7e259..aad0162 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1053,7 +1053,7 @@
 TEST_P(BinderRpc, OnewayStressTest) {
     constexpr size_t kNumClientThreads = 10;
     constexpr size_t kNumServerThreads = 10;
-    constexpr size_t kNumCalls = 500;
+    constexpr size_t kNumCalls = 1000;
 
     auto proc = createRpcTestSocketServerProcess({.numThreads = kNumServerThreads});
 
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index 6c3b3d9..2398e1e 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -197,6 +197,14 @@
     }
 }
 
+TEST(BinderStability, ConnectionInfoRequiresManifestEntries) {
+    sp<IServiceManager> sm = android::defaultServiceManager();
+    sp<IBinder> systemBinder = BadStableBinder::system();
+    EXPECT_EQ(OK, sm->addService(String16("no.connection.foo"), systemBinder));
+    std::optional<android::IServiceManager::ConnectionInfo> connectionInfo;
+    connectionInfo = sm->getConnectionInfo(String16("no.connection.foo"));
+    EXPECT_EQ(connectionInfo, std::nullopt);
+}
 TEST(BinderStability, CantCallVendorBinderInSystemContext) {
     sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
     auto server = interface_cast<IBinderStabilityTest>(serverBinder);
diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp
index 761e45c..9f0754b 100644
--- a/libs/fakeservicemanager/ServiceManager.cpp
+++ b/libs/fakeservicemanager/ServiceManager.cpp
@@ -78,4 +78,10 @@
     return std::nullopt;
 }
 
+std::optional<IServiceManager::ConnectionInfo> ServiceManager::getConnectionInfo(
+        const String16& name) {
+    (void)name;
+    return std::nullopt;
+}
+
 }  // namespace android
diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h
index e26c21b..b1496ba 100644
--- a/libs/fakeservicemanager/ServiceManager.h
+++ b/libs/fakeservicemanager/ServiceManager.h
@@ -51,6 +51,8 @@
 
     std::optional<String16> updatableViaApex(const String16& name) override;
 
+    std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override;
+
 private:
     std::map<String16, sp<IBinder>> mNameToService;
 };