diff options
-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; }; |