summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ServiceManager.cpp28
-rw-r--r--ServiceManager.h2
2 files changed, 25 insertions, 5 deletions
diff --git a/ServiceManager.cpp b/ServiceManager.cpp
index f76afcd..c274d0e 100644
--- a/ServiceManager.cpp
+++ b/ServiceManager.cpp
@@ -314,7 +314,7 @@ Return<bool> ServiceManager::add(const hidl_string& name, const sp<IBase>& servi
return addSuccess;
}
-bool ServiceManager::addImpl(const hidl_string& name,
+bool ServiceManager::addImpl(const std::string& name,
const sp<IBase>& service,
const hidl_vec<hidl_string>& interfaceChain,
const AccessControl::CallingContext& callingContext) {
@@ -332,16 +332,36 @@ bool ServiceManager::addImpl(const hidl_string& name,
}
}
+ // Detect duplicate registration
+ if (interfaceChain.size() > 1) {
+ // second to last entry should be the highest base class other than IBase.
+ const std::string baseFqName = interfaceChain[interfaceChain.size() - 2];
+ const HidlService *hidlService = lookup(baseFqName, name);
+ if (hidlService != nullptr && hidlService->getService() != nullptr) {
+ // This shouldn't occur during normal operation. Here are some cases where
+ // it might get hit:
+ // - bad configuration (service installed on device multiple times)
+ // - race between death notification and a new service being registered
+ // (previous logs should indicate a separate problem)
+ const std::string childFqName = interfaceChain[0];
+ pid_t newServicePid = IPCThreadState::self()->getCallingPid();
+ pid_t oldServicePid = hidlService->getDebugPid();
+ LOG(WARNING) << "Detected instance of " << childFqName << " (pid: " << newServicePid
+ << ") registering over instance of or with base of " << baseFqName << " (pid: "
+ << oldServicePid << ").";
+ }
+ }
+
+ // Unregister superclass if subclass is registered over it
{
// For IBar extends IFoo if IFoo/default is being registered, remove
// IBar/default. This makes sure the following two things are equivalent
// 1). IBar::castFrom(IFoo::getService(X))
// 2). IBar::getService(X)
// assuming that IBar is declared in the device manifest and there
- // is also not an IBaz extends IFoo.
+ // is also not an IBaz extends IFoo and there is no race.
const std::string childFqName = interfaceChain[0];
- const PackageInterfaceMap &ifaceMap = mServiceMap[childFqName];
- const HidlService *hidlService = ifaceMap.lookup(name);
+ const HidlService *hidlService = lookup(childFqName, name);
if (hidlService != nullptr) {
const sp<IBase> remove = hidlService->getService();
diff --git a/ServiceManager.h b/ServiceManager.h
index 8f0c83a..e70110c 100644
--- a/ServiceManager.h
+++ b/ServiceManager.h
@@ -88,7 +88,7 @@ struct ServiceManager : public V1_2::IServiceManager, hidl_death_recipient {
virtual void serviceDied(uint64_t cookie, const wp<IBase>& who);
private:
- bool addImpl(const hidl_string& name,
+ bool addImpl(const std::string& name,
const sp<IBase>& service,
const hidl_vec<hidl_string>& interfaceChain,
const AccessControl::CallingContext& callingContext);