Merge ab/7061308 into stage.
Bug: 180401296
Merged-In: I703d82abf612d2a0c7f0d440da6a3e54eadab302
Change-Id: I88635f0220ad359f57d7bb7e78abb6e35382ab60
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index 68ea8a6..f96b6bb 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -48,6 +48,22 @@
Status onClients(const sp<IBinder>& service, bool clients) override;
private:
+ struct Service {
+ sp<IBinder> service;
+ bool allowIsolated;
+ int dumpFlags;
+
+ // whether, based on onClients calls, we know we have a client for this
+ // service or not
+ bool clients = false;
+ bool registered = true;
+ };
+
+ /**
+ * Looks up a service guaranteed to be registered (service from onClients).
+ */
+ std::map<std::string, Service>::iterator assertRegisteredService(const sp<IBinder>& service);
+
/**
* Unregisters all services that we can. If we can't unregister all, re-register other
* services.
@@ -62,24 +78,13 @@
*/
void maybeTryShutdown();
- /*
- * Counter of the number of services that currently have at least one client.
- */
+ // count of services with clients
size_t mNumConnectedServices;
// previous value passed to the active services callback
std::optional<bool> mPreviousHasClients;
- struct Service {
- sp<IBinder> service;
- bool allowIsolated;
- int dumpFlags;
-
- bool registered = true;
- };
- /**
- * Map of registered names and services
- */
+ // map of registered names and services
std::map<std::string, Service> mRegisteredServices;
bool mForcePersist;
@@ -124,18 +129,34 @@
}
if (!reRegister) {
- if (!manager->registerClientCallback(name, service, this).isOk()) {
+ if(!manager->registerClientCallback(name, service, this).isOk()) {
ALOGE("Failed to add client callback for service %s", name.c_str());
return false;
}
// Only add this when a service is added for the first time, as it is not removed
- mRegisteredServices[name] = {service, allowIsolated, dumpFlags};
+ mRegisteredServices[name] = {
+ .service = service,
+ .allowIsolated = allowIsolated,
+ .dumpFlags = dumpFlags
+ };
}
return true;
}
+std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) {
+ LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
+ for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
+ auto const& [name, registered] = *it;
+ (void) name;
+ if (registered.service != service) continue;
+ return it;
+ }
+ LOG_ALWAYS_FATAL("Got callback on service which we did not register: %s", String8(service->getInterfaceDescriptor()).c_str());
+ __builtin_unreachable();
+}
+
void ClientCounterCallbackImpl::forcePersist(bool persist) {
mForcePersist = persist;
if (!mForcePersist) {
@@ -205,15 +226,25 @@
* invocations could occur on different threads however.
*/
Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
- if (clients) {
- mNumConnectedServices++;
- } else {
- mNumConnectedServices--;
+ auto & [name, registered] = *assertRegisteredService(service);
+ if (registered.clients == clients) {
+ LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
+ "notified has clients: %d", name.c_str(), registered.clients, clients);
+ }
+ registered.clients = clients;
+
+ // update cache count of clients
+ {
+ size_t numWithClients = 0;
+ for (const auto& [name, registered] : mRegisteredServices) {
+ (void) name;
+ if (registered.clients) numWithClients++;
+ }
+ mNumConnectedServices = numWithClients;
}
ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
- mNumConnectedServices, mRegisteredServices.size(),
- String8(service->getInterfaceDescriptor()).string(), clients);
+ mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
maybeTryShutdown();
return Status::ok();
@@ -236,7 +267,7 @@
}
ClientCounterCallback::ClientCounterCallback() {
- mImpl = new ClientCounterCallbackImpl();
+ mImpl = sp<ClientCounterCallbackImpl>::make();
}
bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8bed621..1a4ede1 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1651,7 +1651,10 @@
*outLen = size;
const char* str = (const char*)readInplace(size+1);
if (str != nullptr) {
- return str;
+ if (str[size] == '\0') {
+ return str;
+ }
+ android_errorWriteLog(0x534e4554, "172655291");
}
}
*outLen = 0;
@@ -1689,7 +1692,10 @@
*outLen = size;
const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));
if (str != nullptr) {
- return str;
+ if (str[size] == u'\0') {
+ return str;
+ }
+ android_errorWriteLog(0x534e4554, "172655291");
}
}
*outLen = 0;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 3c90681..0f59de4 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -181,7 +181,7 @@
binder_status_t status = getClass()->onTransact(this, code, &in, &out);
return PruneStatusT(status);
- } else if (code == SHELL_COMMAND_TRANSACTION && getClass()->handleShellCommand != nullptr) {
+ } else if (code == SHELL_COMMAND_TRANSACTION) {
int in = data.readFileDescriptor();
int out = data.readFileDescriptor();
int err = data.readFileDescriptor();
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 6824306..22cacb4 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -116,13 +116,13 @@
const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); }
// required to be non-null, implemented for every class
- const AIBinder_Class_onCreate onCreate = nullptr;
- const AIBinder_Class_onDestroy onDestroy = nullptr;
- const AIBinder_Class_onTransact onTransact = nullptr;
+ const AIBinder_Class_onCreate onCreate;
+ const AIBinder_Class_onDestroy onDestroy;
+ const AIBinder_Class_onTransact onTransact;
// optional methods for a class
- AIBinder_onDump onDump = nullptr;
- AIBinder_handleShellCommand handleShellCommand = nullptr;
+ AIBinder_onDump onDump;
+ AIBinder_handleShellCommand handleShellCommand;
private:
// Copy of the raw char string for when we don't have to return UTF-16
diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp
index 2afe5d2..53b5c3c 100644
--- a/libs/binder/ndk/tests/iface.cpp
+++ b/libs/binder/ndk/tests/iface.cpp
@@ -118,7 +118,7 @@
AIBinder_Weak_delete(mWeakBinder);
}
-AIBinder* IFoo::getBinder() {
+binder_status_t IFoo::addService(const char* instance) {
AIBinder* binder = nullptr;
if (mWeakBinder != nullptr) {
@@ -132,18 +132,8 @@
AIBinder_Weak_delete(mWeakBinder);
}
mWeakBinder = AIBinder_Weak_new(binder);
-
- // WARNING: it is important that this class does not implement debug or
- // shell functions because it does not use special C++ wrapper
- // functions, and so this is how we test those functions.
}
- return binder;
-}
-
-binder_status_t IFoo::addService(const char* instance) {
- AIBinder* binder = getBinder();
-
binder_status_t status = AServiceManager_addService(binder, instance);
// Strong references we care about kept by remote process
AIBinder_decStrong(binder);
diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h
index 7408d0c..244c985 100644
--- a/libs/binder/ndk/tests/include/iface/iface.h
+++ b/libs/binder/ndk/tests/include/iface/iface.h
@@ -31,9 +31,6 @@
static AIBinder_Class* kClass;
- // binder representing this interface with one reference count
- AIBinder* getBinder();
-
// Takes ownership of IFoo
binder_status_t addService(const char* instance);
static ::android::sp<IFoo> getService(const char* instance, AIBinder** outBinder = nullptr);
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index de1a48d..7f725e0 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -241,26 +241,6 @@
AIBinder_decStrong(binder);
}
-TEST(NdkBinder, UnimplementedDump) {
- sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
- ASSERT_NE(foo, nullptr);
- AIBinder* binder = foo->getBinder();
- EXPECT_EQ(OK, AIBinder_dump(binder, STDOUT_FILENO, nullptr, 0));
- AIBinder_decStrong(binder);
-}
-
-TEST(NdkBinder, UnimplementedShell) {
- // libbinder_ndk doesn't support calling shell, so we are calling from the
- // libbinder across processes to the NDK service which doesn't implement
- // shell
- static const sp<android::IServiceManager> sm(android::defaultServiceManager());
- sp<IBinder> testService = sm->getService(String16(IFoo::kSomeInstanceName));
-
- Vector<String16> argsVec;
- EXPECT_EQ(OK, IBinder::shellCommand(testService, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
- argsVec, nullptr, nullptr));
-}
-
TEST(NdkBinder, DoubleNumber) {
sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
ASSERT_NE(foo, nullptr);