diff options
| author | 2021-09-09 22:36:33 +0000 | |
|---|---|---|
| committer | 2021-09-21 21:34:52 +0000 | |
| commit | 5e4c2f1f0958d29b549f08e2c8e7ee7f5b493384 (patch) | |
| tree | 8c993bed71975a43a342291febd77d5e687245e7 | |
| parent | 20f5a270658bcdff7a4cc4f9f0059c572ca123eb (diff) | |
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
| -rw-r--r-- | cmds/dumpsys/tests/dumpsys_test.cpp | 1 | ||||
| -rw-r--r-- | cmds/servicemanager/ServiceManager.cpp | 45 | ||||
| -rw-r--r-- | cmds/servicemanager/ServiceManager.h | 3 | ||||
| -rw-r--r-- | libs/binder/Android.bp | 1 | ||||
| -rw-r--r-- | libs/binder/IServiceManager.cpp | 16 | ||||
| -rw-r--r-- | libs/binder/aidl/android/os/ConnectionInfo.aidl | 33 | ||||
| -rw-r--r-- | libs/binder/aidl/android/os/IServiceManager.aidl | 6 | ||||
| -rw-r--r-- | libs/binder/include/binder/IServiceManager.h | 12 | ||||
| -rw-r--r-- | libs/binder/servicedispatcher.cpp | 5 | ||||
| -rw-r--r-- | libs/binder/tests/binderStabilityTest.cpp | 8 | ||||
| -rw-r--r-- | libs/fakeservicemanager/ServiceManager.cpp | 6 | ||||
| -rw-r--r-- | libs/fakeservicemanager/ServiceManager.h | 2 |
12 files changed, 136 insertions, 2 deletions
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index fa63db5533..677d6c78ea 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -60,6 +60,7 @@ class ServiceManagerMock : public IServiceManager { 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/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index 90db5091e1..4e44ac7323 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -121,6 +121,35 @@ static std::optional<std::string> getVintfUpdatableApex(const std::string& name) 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 @@ Status ServiceManager::updatableViaApex(const std::string& name, 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 4f23c21078..5e403194d7 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 @@ public: 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 98750795d9..3f7d39865f 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -284,6 +284,7 @@ cc_library_static { 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 6e318ea478..aff9e0d48d 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -78,6 +78,7 @@ public: 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 @@ std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& nam 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 0000000000..160c9ea51e --- /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 75c4092559..5880c0a1bd 100644 --- a/libs/binder/aidl/android/os/IServiceManager.aidl +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -19,6 +19,7 @@ package android.os; 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 @@ interface IServiceManager { @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 d152005969..a48075dad1 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 @@ public: * 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 9811cdfc8d..23e34aa8ef 100644 --- a/libs/binder/servicedispatcher.cpp +++ b/libs/binder/servicedispatcher.cpp @@ -157,6 +157,11 @@ public: 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 6c3b3d9087..2398e1e1ef 100644 --- a/libs/binder/tests/binderStabilityTest.cpp +++ b/libs/binder/tests/binderStabilityTest.cpp @@ -197,6 +197,14 @@ TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) { } } +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 761e45c967..9f0754b891 100644 --- a/libs/fakeservicemanager/ServiceManager.cpp +++ b/libs/fakeservicemanager/ServiceManager.cpp @@ -78,4 +78,10 @@ std::optional<String16> ServiceManager::updatableViaApex(const String16& name) { 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 e26c21b9e9..b1496ba50b 100644 --- a/libs/fakeservicemanager/ServiceManager.h +++ b/libs/fakeservicemanager/ServiceManager.h @@ -51,6 +51,8 @@ public: std::optional<String16> updatableViaApex(const String16& name) override; + std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override; + private: std::map<String16, sp<IBinder>> mNameToService; }; |