Merge pie-platform-release to aosp-master - DO NOT MERGE
Change-Id: I14c0233d199fdad4f0171a079bb9c9e6a051951e
diff --git a/AccessControl.cpp b/AccessControl.cpp
index 985feb7..0c73dc6 100644
--- a/AccessControl.cpp
+++ b/AccessControl.cpp
@@ -22,7 +22,7 @@
AccessControl::AccessControl() {
mSeHandle = selinux_android_hw_service_context_handle();
- LOG_ALWAYS_FATAL_IF(mSeHandle == NULL, "Failed to acquire SELinux handle.");
+ LOG_ALWAYS_FATAL_IF(mSeHandle == nullptr, "Failed to acquire SELinux handle.");
if (getcon(&mSeContext) != 0) {
LOG_ALWAYS_FATAL("Failed to acquire hwservicemanager context.");
@@ -38,9 +38,9 @@
}
bool AccessControl::canAdd(const std::string& fqName, const Context &context, pid_t pid) {
- FQName fqIface(fqName);
+ FQName fqIface;
- if (!fqIface.isValid()) {
+ if (!FQName::parse(fqName, &fqIface)) {
return false;
}
const std::string checkName = fqIface.package() + "::" + fqIface.name();
@@ -49,9 +49,9 @@
}
bool AccessControl::canGet(const std::string& fqName, pid_t pid) {
- FQName fqIface(fqName);
+ FQName fqIface;
- if (!fqIface.isValid()) {
+ if (!FQName::parse(fqName, &fqIface)) {
return false;
}
const std::string checkName = fqIface.package() + "::" + fqIface.name();
@@ -64,7 +64,7 @@
}
Context AccessControl::getContext(pid_t sourcePid) {
- char *sourceContext = NULL;
+ char *sourceContext = nullptr;
if (getpidcon(sourcePid, &sourceContext) < 0) {
ALOGE("SELinux: failed to retrieve process context for pid %d", sourcePid);
@@ -92,7 +92,7 @@
}
bool AccessControl::checkPermission(const Context &context, pid_t sourceAuditPid, const char *perm, const char *interface) {
- char *targetContext = NULL;
+ char *targetContext = nullptr;
bool allowed = false;
// Lookup service in hwservice_contexts
diff --git a/HidlService.cpp b/HidlService.cpp
index a0f2cab..56463aa 100644
--- a/HidlService.cpp
+++ b/HidlService.cpp
@@ -3,8 +3,11 @@
#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
+#include <hwbinder/BpHwBinder.h>
#include <sstream>
+using ::android::hardware::interfacesEqual;
+
namespace android {
namespace hidl {
namespace manager {
@@ -28,6 +31,8 @@
mService = service;
mPid = pid;
+ mClientCallbacks.clear();
+
sendRegistrationNotifications();
}
@@ -56,8 +61,6 @@
}
bool HidlService::removeListener(const wp<IBase>& listener) {
- using ::android::hardware::interfacesEqual;
-
bool found = false;
for (auto it = mListeners.begin(); it != mListeners.end();) {
@@ -80,6 +83,61 @@
return mPassthroughClients;
}
+void HidlService::addClientCallback(const sp<IClientCallback>& callback) {
+ mClientCallbacks.push_back(callback);
+}
+
+bool HidlService::removeClientCallback(const sp<IClientCallback>& callback) {
+ bool found = false;
+
+ for (auto it = mClientCallbacks.begin(); it != mClientCallbacks.end();) {
+ if (interfacesEqual(*it, callback)) {
+ it = mClientCallbacks.erase(it);
+ found = true;
+ } else {
+ ++it;
+ }
+ }
+
+ return found;
+}
+
+void HidlService::handleClientCallbacks() {
+ using ::android::hardware::toBinder;
+ using ::android::hardware::BpHwBinder;
+ using ::android::hardware::IBinder;
+
+ if (mClientCallbacks.empty()) return;
+ if (mService == nullptr) return;
+
+ // this justifies the bp cast below, no in-process HALs need this
+ if (!mService->isRemote()) return;
+
+ sp<IBinder> binder = toBinder(mService);
+ if (binder == nullptr) return;
+
+ sp<BpHwBinder> bpBinder = static_cast<BpHwBinder*>(binder.get());
+ ssize_t count = bpBinder->getNodeStrongRefCount();
+
+ // binder driver doesn't support this feature
+ if (count == -1) return;
+
+ bool hasClients = count > 1; // this process holds a strong count
+
+ if (hasClients != mHasClients) {
+ LOG(INFO) << "Notifying " << string() << " they have clients: " << hasClients;
+
+ for (const auto& cb : mClientCallbacks) {
+ Return<void> ret = cb->onClients(getService(), hasClients);
+ if (!ret.isOk()) {
+ LOG(WARNING) << "onClients callback failed for " << string() << ": " << ret.description();
+ }
+ }
+ }
+
+ mHasClients = hasClients;
+}
+
std::string HidlService::string() const {
std::stringstream ss;
ss << mInterfaceName << "/" << mInstanceName;
diff --git a/HidlService.h b/HidlService.h
index 2fcb0d6..96a8aa9 100644
--- a/HidlService.h
+++ b/HidlService.h
@@ -3,7 +3,7 @@
#include <set>
-#include <android/hidl/manager/1.1/IServiceManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
@@ -19,6 +19,7 @@
using ::android::hidl::base::V1_0::IBase;
using ::android::hidl::manager::V1_0::IServiceNotification;
using ::android::hidl::manager::V1_1::IServiceManager;
+using ::android::hidl::manager::V1_2::IClientCallback;
using ::android::sp;
struct HidlService {
@@ -49,6 +50,10 @@
bool removeListener(const wp<IBase> &listener);
void registerPassthroughClient(pid_t pid);
+ void addClientCallback(const sp<IClientCallback>& callback);
+ bool removeClientCallback(const sp<IClientCallback>& callback);
+ void handleClientCallbacks();
+
std::string string() const; // e.x. "android.hidl.manager@1.0::IServiceManager/manager"
const std::set<pid_t> &getPassthroughClients() const;
@@ -62,6 +67,9 @@
std::vector<sp<IServiceNotification>> mListeners{};
std::set<pid_t> mPassthroughClients{};
pid_t mPid = static_cast<pid_t>(IServiceManager::PidConstant::NO_PID);
+
+ std::vector<sp<IClientCallback>> mClientCallbacks{};
+ bool mHasClients = false; // notifications sent on true -> false.
};
} // namespace implementation
diff --git a/ServiceManager.cpp b/ServiceManager.cpp
index 3e2353e..94bb7c6 100644
--- a/ServiceManager.cpp
+++ b/ServiceManager.cpp
@@ -13,6 +13,7 @@
#include <thread>
using android::hardware::IPCThreadState;
+using ::android::hardware::interfacesEqual;
namespace android {
namespace hidl {
@@ -22,45 +23,82 @@
static constexpr uint64_t kServiceDiedCookie = 0;
static constexpr uint64_t kPackageListenerDiedCookie = 1;
static constexpr uint64_t kServiceListenerDiedCookie = 2;
+static constexpr uint64_t kClientCallbackDiedCookie = 3;
size_t ServiceManager::countExistingService() const {
size_t total = 0;
forEachExistingService([&] (const HidlService *) {
++total;
+ return true; // continue
});
return total;
}
-void ServiceManager::forEachExistingService(std::function<void(const HidlService *)> f) const {
- forEachServiceEntry([f] (const HidlService *service) {
+void ServiceManager::forEachExistingService(std::function<bool(const HidlService *)> f) const {
+ forEachServiceEntry([&] (const HidlService *service) {
if (service->getService() == nullptr) {
- return;
+ return true; // continue
}
- f(service);
+ return f(service);
});
}
-void ServiceManager::forEachServiceEntry(std::function<void(const HidlService *)> f) const {
- for (const auto &interfaceMapping : mServiceMap) {
- const auto &instanceMap = interfaceMapping.second.getInstanceMap();
+void ServiceManager::forEachExistingService(std::function<bool(HidlService *)> f) {
+ forEachServiceEntry([&] (HidlService *service) {
+ if (service->getService() == nullptr) {
+ return true; // continue
+ }
+ return f(service);
+ });
+}
- for (const auto &instanceMapping : instanceMap) {
- f(instanceMapping.second.get());
+void ServiceManager::forEachServiceEntry(std::function<bool(const HidlService *)> f) const {
+ for (const auto& interfaceMapping : mServiceMap) {
+ const auto& instanceMap = interfaceMapping.second.getInstanceMap();
+
+ for (const auto& instanceMapping : instanceMap) {
+ if (!f(instanceMapping.second.get())) {
+ return;
+ }
+ }
+ }
+}
+
+void ServiceManager::forEachServiceEntry(std::function<bool(HidlService *)> f) {
+ for (auto& interfaceMapping : mServiceMap) {
+ auto& instanceMap = interfaceMapping.second.getInstanceMap();
+
+ for (auto& instanceMapping : instanceMap) {
+ if (!f(instanceMapping.second.get())) {
+ return;
+ }
}
}
}
void ServiceManager::serviceDied(uint64_t cookie, const wp<IBase>& who) {
+ bool serviceRemoved = false;
switch (cookie) {
case kServiceDiedCookie:
- removeService(who, nullptr /* restrictToInstanceName */);
+ serviceRemoved = removeService(who, nullptr /* restrictToInstanceName */);
break;
case kPackageListenerDiedCookie:
- removePackageListener(who);
+ serviceRemoved = removePackageListener(who);
break;
case kServiceListenerDiedCookie:
- removeServiceListener(who);
+ serviceRemoved = removeServiceListener(who);
break;
+ case kClientCallbackDiedCookie: {
+ sp<IBase> base = who.promote();
+ IClientCallback* callback = static_cast<IClientCallback*>(base.get());
+ serviceRemoved = unregisterClientCallback(nullptr /*service*/,
+ sp<IClientCallback>(callback));
+ } break;
+ }
+
+ if (!serviceRemoved) {
+ LOG(ERROR) << "Received death notification but interface instance not removed. Cookie: "
+ << cookie << " Service pointer: " << who.promote().get();
}
}
@@ -134,8 +172,6 @@
}
bool ServiceManager::PackageInterfaceMap::removePackageListener(const wp<IBase>& who) {
- using ::android::hardware::interfacesEqual;
-
bool found = false;
for (auto it = mPackageListeners.begin(); it != mPackageListeners.end();) {
@@ -151,8 +187,6 @@
}
bool ServiceManager::PackageInterfaceMap::removeServiceListener(const wp<IBase>& who) {
- using ::android::hardware::interfacesEqual;
-
bool found = false;
for (auto &servicePair : getInstanceMap()) {
@@ -192,8 +226,10 @@
return nullptr;
}
- const PackageInterfaceMap &ifaceMap = ifaceIt->second;
- const HidlService *hidlService = ifaceMap.lookup(name);
+ PackageInterfaceMap &ifaceMap = ifaceIt->second;
+
+ // may be modified in post-command task
+ HidlService *hidlService = ifaceMap.lookup(name);
if (hidlService == nullptr) {
tryStartService(fqName, hidlName);
@@ -206,85 +242,101 @@
return nullptr;
}
+ // This is executed immediately after the binder driver confirms the transaction. The driver
+ // will update the appropriate data structures to reflect the fact that the client now has the
+ // service this function is returning. Nothing else can update the HidlService at the same
+ // time. This will run before anything else can modify the HidlService which is owned by this
+ // object, so it will be in the same state that it was when this function returns.
+ hardware::addPostCommandTask([hidlService] {
+ hidlService->handleClientCallbacks();
+ });
+
return service;
}
Return<bool> ServiceManager::add(const hidl_string& name, const sp<IBase>& service) {
- bool isValidService = false;
+ bool addSuccess = false;
if (service == nullptr) {
return false;
}
- // TODO(b/34235311): use HIDL way to determine this
- // also, this assumes that the PID that is registering is the pid that is the service
pid_t pid = IPCThreadState::self()->getCallingPid();
auto context = mAcl.getContext(pid);
auto ret = service->interfaceChain([&](const auto &interfaceChain) {
- if (interfaceChain.size() == 0) {
- return;
- }
-
- // First, verify you're allowed to add() the whole interface hierarchy
- for(size_t i = 0; i < interfaceChain.size(); i++) {
- const std::string fqName = interfaceChain[i];
-
- if (!mAcl.canAdd(fqName, context, pid)) {
- return;
- }
- }
-
- {
- // 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.
- const std::string childFqName = interfaceChain[0];
- const PackageInterfaceMap &ifaceMap = mServiceMap[childFqName];
- const HidlService *hidlService = ifaceMap.lookup(name);
- if (hidlService != nullptr) {
- const sp<IBase> remove = hidlService->getService();
-
- if (remove != nullptr) {
- const std::string instanceName = name;
- removeService(remove, &instanceName /* restrictToInstanceName */);
- }
- }
- }
-
- for(size_t i = 0; i < interfaceChain.size(); i++) {
- const std::string fqName = interfaceChain[i];
-
- PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
- HidlService *hidlService = ifaceMap.lookup(name);
-
- if (hidlService == nullptr) {
- ifaceMap.insertService(
- std::make_unique<HidlService>(fqName, name, service, pid));
- } else {
- hidlService->setService(service, pid);
- }
-
- ifaceMap.sendPackageRegistrationNotification(fqName, name);
- }
-
- bool linkRet = service->linkToDeath(this, kServiceDiedCookie).withDefault(false);
- if (!linkRet) {
- LOG(ERROR) << "Could not link to death for " << interfaceChain[0] << "/" << name;
- }
-
- isValidService = true;
+ addSuccess = addImpl(name, service, interfaceChain, context, pid);
});
if (!ret.isOk()) {
- LOG(ERROR) << "Failed to retrieve interface chain.";
+ LOG(ERROR) << "Failed to retrieve interface chain: " << ret.description();
return false;
}
- return isValidService;
+ return addSuccess;
+}
+
+bool ServiceManager::addImpl(const hidl_string& name,
+ const sp<IBase>& service,
+ const hidl_vec<hidl_string>& interfaceChain,
+ const AccessControl::Context &context,
+ pid_t pid) {
+ if (interfaceChain.size() == 0) {
+ LOG(WARNING) << "Empty interface chain for " << name;
+ return false;
+ }
+
+ // First, verify you're allowed to add() the whole interface hierarchy
+ for(size_t i = 0; i < interfaceChain.size(); i++) {
+ const std::string fqName = interfaceChain[i];
+
+ if (!mAcl.canAdd(fqName, context, pid)) {
+ return false;
+ }
+ }
+
+ {
+ // 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.
+ const std::string childFqName = interfaceChain[0];
+ const PackageInterfaceMap &ifaceMap = mServiceMap[childFqName];
+ const HidlService *hidlService = ifaceMap.lookup(name);
+ if (hidlService != nullptr) {
+ const sp<IBase> remove = hidlService->getService();
+
+ if (remove != nullptr) {
+ const std::string instanceName = name;
+ removeService(remove, &instanceName /* restrictToInstanceName */);
+ }
+ }
+ }
+
+ for(size_t i = 0; i < interfaceChain.size(); i++) {
+ const std::string fqName = interfaceChain[i];
+
+ PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
+ HidlService *hidlService = ifaceMap.lookup(name);
+
+ if (hidlService == nullptr) {
+ ifaceMap.insertService(
+ std::make_unique<HidlService>(fqName, name, service, pid));
+ } else {
+ hidlService->setService(service, pid);
+ }
+
+ ifaceMap.sendPackageRegistrationNotification(fqName, name);
+ }
+
+ bool linkRet = service->linkToDeath(this, kServiceDiedCookie).withDefault(false);
+ if (!linkRet) {
+ LOG(ERROR) << "Could not link to death for " << interfaceChain[0] << "/" << name;
+ }
+
+ return true;
}
Return<ServiceManager::Transport> ServiceManager::getTransport(const hidl_string& fqName,
@@ -321,6 +373,7 @@
size_t idx = 0;
forEachExistingService([&] (const HidlService *service) {
list[idx++] = service->string();
+ return true; // continue
});
_hidl_cb(list);
@@ -381,8 +434,8 @@
PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
if (name.empty()) {
- auto ret = callback->linkToDeath(this, kPackageListenerDiedCookie);
- if (!ret.isOk()) {
+ bool ret = callback->linkToDeath(this, kPackageListenerDiedCookie).withDefault(false);
+ if (!ret) {
LOG(ERROR) << "Failed to register death recipient for " << fqName << "/" << name;
return false;
}
@@ -392,8 +445,8 @@
HidlService *service = ifaceMap.lookup(name);
- auto ret = callback->linkToDeath(this, kServiceListenerDiedCookie);
- if (!ret.isOk()) {
+ bool ret = callback->linkToDeath(this, kServiceListenerDiedCookie).withDefault(false);
+ if (!ret) {
LOG(ERROR) << "Failed to register death recipient for " << fqName << "/" << name;
return false;
}
@@ -445,6 +498,80 @@
return service->removeListener(callback);
}
+Return<bool> ServiceManager::registerClientCallback(const sp<IBase>& server,
+ const sp<IClientCallback>& cb) {
+ if (server == nullptr || cb == nullptr) return false;
+
+ // only the server of the interface can register a client callback
+ pid_t pid = IPCThreadState::self()->getCallingPid();
+
+ HidlService* registered = nullptr;
+
+ forEachExistingService([&] (HidlService *service) {
+ if (service->getPid() != pid) {
+ return true; // continue
+ }
+
+ if (interfacesEqual(service->getService(), server)) {
+ service->addClientCallback(cb);
+ registered = service;
+ return false; // break
+ }
+ return true; // continue
+ });
+
+ if (registered != nullptr) {
+ bool linkRet = cb->linkToDeath(this, kClientCallbackDiedCookie).withDefault(false);
+ if (!linkRet) {
+ LOG(ERROR) << "Could not link to death for registerClientCallback";
+ unregisterClientCallback(server, cb);
+ registered = nullptr;
+ }
+ }
+
+ if (registered != nullptr) {
+ registered->handleClientCallbacks();
+ }
+
+ return registered != nullptr;
+}
+
+Return<bool> ServiceManager::unregisterClientCallback(const sp<IBase>& server,
+ const sp<IClientCallback>& cb) {
+ if (cb == nullptr) return false;
+
+ bool removed = false;
+
+ forEachExistingService([&] (HidlService *service) {
+ if (server == nullptr || interfacesEqual(service->getService(), server)) {
+ removed |= service->removeClientCallback(cb);
+ }
+ return true; // continue
+ });
+
+ return removed;
+}
+
+void ServiceManager::handleClientCallbacks() {
+ forEachServiceEntry([&] (HidlService *service) {
+ service->handleClientCallbacks();
+ return true; // continue
+ });
+}
+
+Return<bool> ServiceManager::addWithChain(const hidl_string& name,
+ const sp<IBase>& service,
+ const hidl_vec<hidl_string>& chain) {
+ if (service == nullptr) {
+ return false;
+ }
+
+ pid_t pid = IPCThreadState::self()->getCallingPid();
+ auto context = mAcl.getContext(pid);
+
+ return addImpl(name, service, chain, context, pid);
+}
+
Return<void> ServiceManager::debugDump(debugDump_cb _cb) {
pid_t pid = IPCThreadState::self()->getCallingPid();
if (!mAcl.canList(pid)) {
@@ -469,6 +596,8 @@
.clientPids = clientPids,
.arch = ::android::hidl::base::V1_0::DebugInfo::Architecture::UNKNOWN
});
+
+ return true; // continue
});
_cb(list);
@@ -508,8 +637,6 @@
}
bool ServiceManager::removeService(const wp<IBase>& who, const std::string* restrictToInstanceName) {
- using ::android::hardware::interfacesEqual;
-
bool keepInstance = false;
bool removed = false;
for (auto &interfaceMapping : mServiceMap) {
diff --git a/ServiceManager.h b/ServiceManager.h
index 54ecb37..44936d5 100644
--- a/ServiceManager.h
+++ b/ServiceManager.h
@@ -1,7 +1,7 @@
#ifndef ANDROID_HARDWARE_MANAGER_SERVICEMANAGER_H
#define ANDROID_HARDWARE_MANAGER_SERVICEMANAGER_H
-#include <android/hidl/manager/1.1/IServiceManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
#include <map>
@@ -20,12 +20,12 @@
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hidl::base::V1_0::IBase;
-using ::android::hidl::manager::V1_1::IServiceManager;
using ::android::hidl::manager::V1_0::IServiceNotification;
+using ::android::hidl::manager::V1_2::IClientCallback;
using ::android::sp;
using ::android::wp;
-struct ServiceManager : public IServiceManager, hidl_death_recipient {
+struct ServiceManager : public V1_2::IServiceManager, hidl_death_recipient {
// Methods from ::android::hidl::manager::V1_0::IServiceManager follow.
Return<sp<IBase>> get(const hidl_string& fqName,
const hidl_string& name) override;
@@ -52,16 +52,37 @@
const hidl_string& name,
const sp<IServiceNotification>& callback) override;
+ // Methods from ::android::hidl::manager::V1_2::IServiceManager follow.
+ Return<bool> registerClientCallback(const sp<IBase>& server,
+ const sp<IClientCallback>& cb) override;
+ Return<bool> unregisterClientCallback(const sp<IBase>& server,
+ const sp<IClientCallback>& cb) override;
+ Return<bool> addWithChain(const hidl_string& name,
+ const sp<IBase>& service,
+ const hidl_vec<hidl_string>& chain) override;
+
+ void handleClientCallbacks();
+
virtual void serviceDied(uint64_t cookie, const wp<IBase>& who);
private:
+ bool addImpl(const hidl_string& name,
+ const sp<IBase>& service,
+ const hidl_vec<hidl_string>& interfaceChain,
+ const AccessControl::Context &context,
+ pid_t pid);
+
// if restrictToInstanceName is nullptr, remove all, otherwise only those services
// which match this instance name. Returns whether all instances were removed.
bool removeService(const wp<IBase>& who, const std::string* restrictToInstanceName);
bool removePackageListener(const wp<IBase>& who);
bool removeServiceListener(const wp<IBase>& who);
size_t countExistingService() const;
- void forEachExistingService(std::function<void(const HidlService *)> f) const;
- void forEachServiceEntry(std::function<void(const HidlService *)> f) const;
+
+ // true = continue, false = break
+ void forEachExistingService(std::function<bool(const HidlService *)> f) const;
+ void forEachExistingService(std::function<bool(HidlService *)> f);
+ void forEachServiceEntry(std::function<bool(const HidlService *)> f) const;
+ void forEachServiceEntry(std::function<bool(HidlService *)> f);
using InstanceMap = std::map<
std::string, // instance name e.x. "manager"
diff --git a/Vintf.cpp b/Vintf.cpp
index d2d2f00..989adc0 100644
--- a/Vintf.cpp
+++ b/Vintf.cpp
@@ -23,8 +23,9 @@
}
vintf::Transport getTransport(const std::string &interfaceName, const std::string &instanceName) {
- FQName fqName(interfaceName);
- if (!fqName.isValid()) {
+ FQName fqName;
+
+ if (!FQName::parse(interfaceName, &fqName)) {
LOG(ERROR) << __FUNCTION__ << ": " << interfaceName
<< " is not a valid fully-qualified name ";
return vintf::Transport::EMPTY;
diff --git a/service.cpp b/service.cpp
index 17db6bc..5b595b8 100644
--- a/service.cpp
+++ b/service.cpp
@@ -4,10 +4,12 @@
#include <inttypes.h>
#include <unistd.h>
+#include <sys/timerfd.h>
-#include <android/hidl/manager/1.1/BnHwServiceManager.h>
#include <android/hidl/token/1.0/ITokenManager.h>
#include <cutils/properties.h>
+#include <hidl/HidlBinderSupport.h>
+#include <hidl/HidlTransportSupport.h>
#include <hidl/Status.h>
#include <hwbinder/IPCThreadState.h>
#include <hwbinder/ProcessState.h>
@@ -20,45 +22,117 @@
// libutils:
using android::sp;
-using android::status_t;
+using android::Looper;
+using android::LooperCallback;
// libhwbinder:
+using android::hardware::BHwBinder;
+using android::hardware::IBinder;
using android::hardware::IPCThreadState;
using android::hardware::ProcessState;
// libhidl
-using android::hardware::configureRpcThreadpool;
-using android::hardware::hidl_string;
-using android::hardware::hidl_vec;
-using android::hardware::joinRpcThreadpool;
-
-// hidl types
-using android::hidl::manager::V1_1::BnHwServiceManager;
-using android::hidl::token::V1_0::ITokenManager;
+using android::hardware::handleTransportPoll;
+using android::hardware::setupTransportPolling;
+using android::hardware::toBinder;
// implementations
using android::hidl::manager::implementation::ServiceManager;
+using android::hidl::manager::V1_0::IServiceManager;
using android::hidl::token::V1_0::implementation::TokenManager;
static std::string serviceName = "default";
+class HwBinderCallback : public LooperCallback {
+public:
+ static sp<HwBinderCallback> setupTo(const sp<Looper>& looper) {
+ sp<HwBinderCallback> cb = new HwBinderCallback;
+
+ int fdHwBinder = setupTransportPolling();
+ LOG_ALWAYS_FATAL_IF(fdHwBinder < 0, "Failed to setupTransportPolling: %d", fdHwBinder);
+
+ // Flush after setupPolling(), to make sure the binder driver
+ // knows about this thread handling commands.
+ IPCThreadState::self()->flushCommands();
+
+ int ret = looper->addFd(fdHwBinder,
+ Looper::POLL_CALLBACK,
+ Looper::EVENT_INPUT,
+ cb,
+ nullptr /*data*/);
+ LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");
+
+ return cb;
+ }
+
+ int handleEvent(int fd, int /*events*/, void* /*data*/) override {
+ handleTransportPoll(fd);
+ return 1; // Continue receiving callbacks.
+ }
+};
+
+// LooperCallback for IClientCallback
+class ClientCallbackCallback : public LooperCallback {
+public:
+ static sp<ClientCallbackCallback> setupTo(const sp<Looper>& looper, const sp<ServiceManager>& manager) {
+ sp<ClientCallbackCallback> cb = new ClientCallbackCallback(manager);
+
+ int fdTimer = timerfd_create(CLOCK_MONOTONIC, 0 /*flags*/);
+ LOG_ALWAYS_FATAL_IF(fdTimer < 0, "Failed to timerfd_create: fd: %d err: %d", fdTimer, errno);
+
+ itimerspec timespec {
+ .it_interval = {
+ .tv_sec = 5,
+ .tv_nsec = 0,
+ },
+ .it_value = {
+ .tv_sec = 5,
+ .tv_nsec = 0,
+ },
+ };
+
+ int timeRes = timerfd_settime(fdTimer, 0 /*flags*/, ×pec, nullptr);
+ LOG_ALWAYS_FATAL_IF(timeRes < 0, "Failed to timerfd_settime: res: %d err: %d", timeRes, errno);
+
+ int addRes = looper->addFd(fdTimer,
+ Looper::POLL_CALLBACK,
+ Looper::EVENT_INPUT,
+ cb,
+ nullptr);
+ LOG_ALWAYS_FATAL_IF(addRes != 1, "Failed to add client callback FD to Looper");
+
+ return cb;
+ }
+
+ int handleEvent(int fd, int /*events*/, void* /*data*/) override {
+ uint64_t expirations;
+ int ret = read(fd, &expirations, sizeof(expirations));
+ if (ret != sizeof(expirations)) {
+ ALOGE("Read failed to callback FD: ret: %d err: %d", ret, errno);
+ }
+
+ mManager->handleClientCallbacks();
+ return 1; // Continue receiving callbacks.
+ }
+private:
+ ClientCallbackCallback(const sp<ServiceManager>& manager) : mManager(manager) {}
+ sp<ServiceManager> mManager;
+};
+
int main() {
- configureRpcThreadpool(1, true /* callerWillJoin */);
-
- ServiceManager *manager = new ServiceManager();
-
+ sp<ServiceManager> manager = new ServiceManager();
if (!manager->add(serviceName, manager)) {
ALOGE("Failed to register hwservicemanager with itself.");
}
- TokenManager *tokenManager = new TokenManager();
-
+ sp<TokenManager> tokenManager = new TokenManager();
if (!manager->add(serviceName, tokenManager)) {
ALOGE("Failed to register ITokenManager with hwservicemanager.");
}
// Tell IPCThreadState we're the service manager
- sp<BnHwServiceManager> service = new BnHwServiceManager(manager);
+ sp<IBinder> binder = toBinder<IServiceManager>(manager);
+ sp<BHwBinder> service = static_cast<BHwBinder*>(binder.get()); // local binder object
IPCThreadState::self()->setTheContextObject(service);
// Then tell the kernel
ProcessState::self()->becomeContextManager(nullptr, nullptr);
@@ -69,8 +143,16 @@
"HAL services will not start!\n", rc);
}
+ sp<Looper> looper = Looper::prepare(0 /* opts */);
+
+ (void)HwBinderCallback::setupTo(looper);
+ (void)ClientCallbackCallback::setupTo(looper, manager);
+
ALOGI("hwservicemanager is ready now.");
- joinRpcThreadpool();
+
+ while (true) {
+ looper->pollAll(-1 /* timeoutMillis */);
+ }
return 0;
}