Add getConnectionInfo API to service manager

This gets connection info from the vintf manifest for AIDL hals that
report it.
The hals will have new "ip" and "port" fields in their entries if they
are serving the interface from a remote device at that ip address/port
combo.

Test: tested the IServiceManager API with an internal POC using a remote HAL
Test: atest binderStabilityTest
Bug: 198207801
Change-Id: I334bebe62afb40e9710b57257f95e37a9c2b8226
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 9875079..3f7d398 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -284,6 +284,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/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/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/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;
 };