Merge "libbinder: allow externally created connections"
diff --git a/cmds/cmd/fuzzer/Android.bp b/cmds/cmd/fuzzer/Android.bp
index 0c78c5a..8262bc2 100644
--- a/cmds/cmd/fuzzer/Android.bp
+++ b/cmds/cmd/fuzzer/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_cmds_cmd_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_cmds_cmd_license"],
+}
+
cc_fuzz {
name: "cmd_fuzzer",
srcs: [
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 6ab25e0..879e462 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -66,14 +66,13 @@
return setupSocketServer(VsockSocketAddress(kAnyCid, port));
}
-bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) {
- const char* kAddr = "127.0.0.1";
-
+bool RpcServer::setupInetServer(const char* address, unsigned int port,
+ unsigned int* assignedPort) {
if (assignedPort != nullptr) *assignedPort = 0;
- auto aiStart = InetSocketAddress::getAddrInfo(kAddr, port);
+ auto aiStart = InetSocketAddress::getAddrInfo(address, port);
if (aiStart == nullptr) return false;
for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
- InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, kAddr, port);
+ InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, address, port);
if (!setupSocketServer(socketAddress)) {
continue;
}
@@ -100,7 +99,7 @@
return true;
}
- ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr,
+ ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", address,
port);
return false;
}
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 572595d..7565f1b 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -696,6 +696,12 @@
std::unique_ptr<RpcTransport> rpcTransport) {
std::lock_guard<std::mutex> _l(mMutex);
+ if (mIncomingConnections.size() >= mMaxThreads) {
+ ALOGE("Cannot add thread to session with %zu threads (max is set to %zu)",
+ mIncomingConnections.size(), mMaxThreads);
+ return nullptr;
+ }
+
// Don't accept any more connections, some have shutdown. Usually this
// happens when new connections are still being established as part of a
// very short-lived session which shuts down after it already started
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 0fdab9c..4abf3b9 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -74,8 +74,14 @@
* Set |port| to 0 to pick an ephemeral port; see discussion of
* /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort|
* will be set to the picked port number, if it is not null.
+ *
+ * Set the IPv4 address for the socket to be listening on.
+ * "127.0.0.1" allows for local connections from the same device.
+ * "0.0.0.0" allows for connections on any IP address that the device may
+ * have
*/
- [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort);
+ [[nodiscard]] bool setupInetServer(const char* address, unsigned int port,
+ unsigned int* assignedPort);
/**
* If setup*Server has been successful, return true. Otherwise return false.
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index 6c44726..70a3906 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -43,31 +43,23 @@
namespace ndk {
/**
- * analog using std::shared_ptr for internally held refcount
- *
* ref must be called at least one time during the lifetime of this object. The recommended way to
* construct this object is with SharedRefBase::make.
+ *
+ * Note - this class used to not inherit from enable_shared_from_this, so
+ * std::make_shared works, but it won't be portable against old copies of this
+ * class.
*/
-class SharedRefBase {
+class SharedRefBase : public std::enable_shared_from_this<SharedRefBase> {
public:
SharedRefBase() {}
- virtual ~SharedRefBase() {
- std::call_once(mFlagThis, [&]() {
- __assert(__FILE__, __LINE__, "SharedRefBase: no ref created during lifetime");
- });
- }
+ virtual ~SharedRefBase() {}
/**
* A shared_ptr must be held to this object when this is called. This must be called once during
* the lifetime of this object.
*/
- std::shared_ptr<SharedRefBase> ref() {
- std::shared_ptr<SharedRefBase> thiz = mThis.lock();
-
- std::call_once(mFlagThis, [&]() { mThis = thiz = std::shared_ptr<SharedRefBase>(this); });
-
- return thiz;
- }
+ std::shared_ptr<SharedRefBase> ref() { return shared_from_this(); }
/**
* Convenience method for a ref (see above) which automatically casts to the desired child type.
@@ -86,8 +78,13 @@
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
T* t = new T(std::forward<Args>(args)...);
#pragma clang diagnostic pop
- // warning: Potential leak of memory pointed to by 't' [clang-analyzer-unix.Malloc]
- return t->template ref<T>(); // NOLINT(clang-analyzer-unix.Malloc)
+
+ // T may have a private (though necessarily virtual!) destructor, so we
+ // can't use refbase. For getting the first ref, we don't use ref()
+ // since the internal shared_ptr isn't guaranteed to exist yet.
+ SharedRefBase* base = static_cast<SharedRefBase*>(t);
+ std::shared_ptr<SharedRefBase> strongBase(base);
+ return std::static_pointer_cast<T>(strongBase);
}
static void operator delete(void* p) { std::free(p); }
@@ -100,13 +97,9 @@
#if !defined(__ANDROID_API__) || __ANDROID_API__ >= 30 || defined(__ANDROID_APEX__)
private:
#else
- [[deprecated("Prefer SharedRefBase::make<T>(...) if possible.")]]
+ [[deprecated("Prefer SharedRefBase::make<T>(...) or std::make_shared<T>() if possible.")]]
#endif
static void* operator new(size_t s) { return std::malloc(s); }
-
- private:
- std::once_flag mFlagThis;
- std::weak_ptr<SharedRefBase> mThis;
};
/**
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 5ad390e..94cc086 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -54,6 +54,15 @@
constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
+ public:
+ MyBinderNdkUnitTest() = default;
+ MyBinderNdkUnitTest(bool* deleted) : deleted(deleted) {}
+ ~MyBinderNdkUnitTest() {
+ if (deleted) {
+ *deleted = true;
+ }
+ }
+
ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
*out = in;
return ndk::ScopedAStatus::ok();
@@ -122,6 +131,7 @@
}
uint64_t contextTestValue = kContextTestValue;
+ bool* deleted = nullptr;
};
int generatedService() {
@@ -224,6 +234,27 @@
return true;
}
+TEST(NdkBinder, MakeShared) {
+ const char* kInstance = "make_shared_test_instance";
+ bool deleted = false;
+
+ {
+ auto service = std::make_shared<MyBinderNdkUnitTest>(&deleted);
+ auto binder = service->asBinder();
+ ASSERT_EQ(EX_NONE, AServiceManager_addService(binder.get(), kInstance));
+ auto binder2 = ndk::SpAIBinder(AServiceManager_checkService(kInstance));
+ ASSERT_EQ(binder.get(), binder2.get());
+
+ // overwrite service
+ ASSERT_EQ(EX_NONE,
+ AServiceManager_addService(
+ std::make_shared<MyBinderNdkUnitTest>(&deleted)->asBinder().get(),
+ kInstance));
+ }
+
+ EXPECT_TRUE(deleted);
+}
+
TEST(NdkBinder, GetServiceThatDoesntExist) {
sp<IFoo> foo = IFoo::getService("asdfghkl;");
EXPECT_EQ(nullptr, foo.get());
diff --git a/libs/binder/rust/tests/ndk_rust_interop.rs b/libs/binder/rust/tests/ndk_rust_interop.rs
index 4702e45..415ede1 100644
--- a/libs/binder/rust/tests/ndk_rust_interop.rs
+++ b/libs/binder/rust/tests/ndk_rust_interop.rs
@@ -90,7 +90,7 @@
pub unsafe extern "C" fn rust_start_service(service_name: *const c_char) -> c_int {
let service_name = CStr::from_ptr(service_name).to_str().unwrap();
let service = BnBinderRustNdkInteropTest::new_binder(Service, BinderFeatures::default());
- match binder::add_service(&service_name, service.as_binder()) {
+ match binder::add_service(service_name, service.as_binder()) {
Ok(_) => StatusCode::OK as c_int,
Err(e) => e as c_int,
}
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 62df9b7..a6e3f7d 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -47,6 +47,7 @@
namespace {
+const char* kLocalInetAddress = "127.0.0.1";
using ServiceRetriever = decltype(&android::IServiceManager::checkService);
int Usage(const char* program) {
@@ -86,7 +87,7 @@
}
rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
unsigned int port;
- if (!rpcServer->setupInetServer(0, &port)) {
+ if (!rpcServer->setupInetServer(kLocalInetAddress, 0, &port)) {
LOG(ERROR) << "setupInetServer failed";
return EX_SOFTWARE;
}
@@ -199,7 +200,7 @@
rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
rpcServer->setRootObject(service);
unsigned int port;
- if (!rpcServer->setupInetServer(0, &port)) {
+ if (!rpcServer->setupInetServer(kLocalInetAddress, 0, &port)) {
LOG(ERROR) << "Unable to set up inet server";
return EX_SOFTWARE;
}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 4c3225f..65db7f6 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -1192,7 +1192,7 @@
if (rpcServer == nullptr) return {};
rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
unsigned int port;
- if (!rpcServer->setupInetServer(0, &port)) {
+ if (!rpcServer->setupInetServer("127.0.0.1", 0, &port)) {
ADD_FAILURE() << "setupInetServer failed";
return {};
}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 6c56a4d..36a6804 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -52,6 +52,7 @@
static_assert(RPC_WIRE_PROTOCOL_VERSION + 1 == RPC_WIRE_PROTOCOL_VERSION_NEXT ||
RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL);
+const char* kLocalInetAddress = "127.0.0.1";
enum class RpcSecurity { RAW };
@@ -489,7 +490,7 @@
CHECK(server->setupVsockServer(vsockPort));
break;
case SocketType::INET: {
- CHECK(server->setupInetServer(0, &outPort));
+ CHECK(server->setupInetServer(kLocalInetAddress, 0, &outPort));
CHECK_NE(0, outPort);
break;
}
@@ -1314,7 +1315,7 @@
auto rpcServer = RpcServer::make();
rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
unsigned int port;
- ASSERT_TRUE(rpcServer->setupInetServer(0, &port));
+ ASSERT_TRUE(rpcServer->setupInetServer(kLocalInetAddress, 0, &port));
auto socket = rpcServer->releaseServer();
auto keepAlive = sp<BBinder>::make();